From 2df71007179fd5905df33e0925c6afc7ece70699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E4=BD=A0=E4=B8=AA=E6=97=BA=E5=91=80?= Date: Wed, 22 Jan 2025 00:14:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=98=80=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E6=94=AF=E4=BB=98=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configuration/Alipay.json | 37 ++- .../Entity/SysAlipayAuthInfo.cs | 149 ++++++++++ .../Entity/SysAlipayTransaction.cs | 108 +++++++ .../Admin.NET.Core/Option/AlipayOptions.cs | 97 ++++-- .../Service/Alipay/AlipayService.cs | 279 ------------------ .../Service/Alipay/Dto/AlipayInput.cs | 32 +- .../Service/Alipay/SysAlipayService.cs | 271 +++++++++++++++++ .../Alipaycrt/alipayPublicCert.crt | 38 +++ .../Alipaycrt/alipayRootCert.crt | 88 ++++++ .../Alipaycrt/appPublicCert.crt | 19 ++ 10 files changed, 796 insertions(+), 322 deletions(-) create mode 100644 Admin.NET/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs create mode 100644 Admin.NET/Admin.NET.Core/Entity/SysAlipayTransaction.cs delete mode 100644 Admin.NET/Admin.NET.Core/Service/Alipay/AlipayService.cs create mode 100644 Admin.NET/Admin.NET.Core/Service/Alipay/SysAlipayService.cs create mode 100644 Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayPublicCert.crt create mode 100644 Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayRootCert.crt create mode 100644 Admin.NET/Admin.NET.Web.Entry/Alipaycrt/appPublicCert.crt diff --git a/Admin.NET/Admin.NET.Application/Configuration/Alipay.json b/Admin.NET/Admin.NET.Application/Configuration/Alipay.json index 3c1e24fc..585b9af3 100644 --- a/Admin.NET/Admin.NET.Application/Configuration/Alipay.json +++ b/Admin.NET/Admin.NET.Application/Configuration/Alipay.json @@ -3,16 +3,33 @@ // 支付宝支付配置,文档地址:https://openhome.alipay.com/develop/sandbox/app "Alipay": { - "AppId": "9000000000000000", // 支付宝 APPID - "AlipayWebsocketUrl": "openchannel-sandbox.dl.alipaydev.com", // websocket服务地址 "ServerUrl": "https://openapi-sandbox.dl.alipaydev.com/gateway.do", // 支付宝网关地址 - "AuthUrl": "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm", // 授权回调地址 - "NotifyUrl": "http://xxxx.xxx/api/Alipay/Notify", // 应用网关地址 - "PrivateKey": "xxxxxxxxx", // 应用私钥 - "SignType": "RSA2", // 加密算法 - "EncryptKey": "xxxxxxxx", // 从支付宝获取敏感信息时的加密密钥 - "AlipayPublicCertPath": "/AlipayCrt/alipayPublicCert.crt", // 支付宝公钥证书存放路径 - "RootCertPath": "/AlipayCrt/alipayRootCert.crt", // 支付宝根证书存放路径 - "AppCertPath": "/AlipayCrt/appPublicCert.crt" // 应用公钥证书存放路径 + "WebsocketUrl": "openchannel-sandbox.dl.alipaydev.com", // websocket服务地址 + //"AuthUrl": "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm", // 正式环境授权回调地址 + "AuthUrl": "https://openauth-sandbox.dl.alipaydev.com/oauth2/publicAppAuthorize.htm", // 沙箱环境授权回调地址 + "AppAuthUrl": "http://xxxxxxxxxx", // 应用授权回调地址 + "NotifyUrl": "http://xxxxxxxxx/api/sysAlipay/Notify", // 应用网关地址 + "RootCertPath": "Alipaycrt/alipayRootCert.crt", // 支付宝根证书存放路径 + "AccountList": [ + { + "Name": "sandbox 默认应用", + "AppId": "xxxxxxxxxxxxxx", + "SignType": "RSA2", + "PrivateKey": "xxxxxxxxxxxxxxxxx", + "EncryptKey": "xxxxxxxxxxxxxxxxxxxx", + "AppCertPath": "Alipaycrt/appPublicCert.crt", // 应用公钥证书存放路径 + "AlipayPublicCertPath": "Alipaycrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径 + + }, + { + "Name": "sandbox 默认应用2", + "AppId": "xxxxxxxxxxxxxx", + "SignType": "RSA2", + "PrivateKey": "xxxxxxxxxxxxxxxxx", + "EncryptKey": "xxxxxxxxxxxxxxxxxxxx", + "AppCertPath": "Alipaycrt/appPublicCert.crt", // 应用公钥证书存放路径 + "AlipayPublicCertPath": "Alipaycrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径 + } + ] } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs b/Admin.NET/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs new file mode 100644 index 00000000..3c2aa307 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs @@ -0,0 +1,149 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 支付宝授权记录表 +/// +[SysTable] +[SugarTable(null, "支付宝授权记录表")] +[SugarIndex("index_{table}_U", nameof(UserId), OrderByType.Asc)] +[SugarIndex("index_{table}_T", nameof(OpenId), OrderByType.Asc)] +public class SysAlipayAuthInfo : EntityBase +{ + /// + /// 商户AppId + /// + [SugarColumn(ColumnDescription = "商户AppId", Length = 64)] + public string? AppId { get; set; } + + /// + /// 开放ID + /// + [SugarColumn(ColumnDescription = "开放ID", Length = 64)] + public string? OpenId { get; set; } + + /// + /// 用户ID + /// + [SugarColumn(ColumnDescription = "用户ID", Length = 64)] + public string? UserId { get; set; } + + /// + /// 性别 + /// + [SugarColumn(ColumnDescription = "性别", Length = 8)] + public GenderEnum Gender { get; set; } + + /// + /// 年龄 + /// + [SugarColumn(ColumnDescription = "年龄", Length = 16)] + public int Age { get; set; } + + /// + /// 手机号 + /// + [SugarColumn(ColumnDescription = "手机号", Length = 32)] + public string Mobile { get; set; } + + /// + /// 显示名称 + /// + [SugarColumn(ColumnDescription = "显示名称", Length = 128)] + public string DisplayName { get; set; } + + /// + /// 昵称 + /// + [SugarColumn(ColumnDescription = "昵称", Length = 64)] + public string NickName { get; set; } + + /// + /// 用户名 + /// + [SugarColumn(ColumnDescription = "用户名", Length = 64)] + public string UserName { get; set; } + + /// + /// 头像 + /// + [SugarColumn(ColumnDescription = "头像", Length = 512)] + public string? Avatar { get; set; } + + /// + /// 邮箱 + /// + [SugarColumn(ColumnDescription = "邮箱", Length = 128)] + public string? Email { get; set; } + + /// + /// 用户民族 + /// + [SugarColumn(ColumnDescription = "用户民族", Length = 32)] + public string? UserNation { get; set; } + + /// + /// 淘宝ID + /// + [SugarColumn(ColumnDescription = "淘宝ID", Length = 64)] + public string? TaobaoId { get; set; } + + /// + /// 电话 + /// + [SugarColumn(ColumnDescription = "电话", Length = 32)] + public string? Phone { get; set; } + + /// + /// 生日 + /// + [SugarColumn(ColumnDescription = "生日", Length = 32)] + public string? PersonBirthday { get; set; } + + /// + /// 职业 + /// + [SugarColumn(ColumnDescription = "职业", Length = 64)] + public string? Profession { get; set; } + + /// + /// 省份 + /// + [SugarColumn(ColumnDescription = "省份", Length = 64)] + public string? Province { get; set; } + + /// + /// 用户状态 + /// + [SugarColumn(ColumnDescription = "用户状态", Length = 32)] + public string? UserStatus { get; set; } + + /// + /// 学历 + /// + [SugarColumn(ColumnDescription = "学历", Length = 32)] + public string? Degree { get; set; } + + /// + /// 用户类型 + /// + [SugarColumn(ColumnDescription = "用户类型", Length = 32)] + public string? UserType { get; set; } + + /// + /// 邮编 + /// + [SugarColumn(ColumnDescription = "邮编", Length = 16)] + public string? Zip { get; set; } + + /// + /// 地址 + /// + [SugarColumn(ColumnDescription = "地址", Length = 256)] + public string? Address { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysAlipayTransaction.cs b/Admin.NET/Admin.NET.Core/Entity/SysAlipayTransaction.cs new file mode 100644 index 00000000..5ca95bcf --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysAlipayTransaction.cs @@ -0,0 +1,108 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 支付宝交易记录表 +/// +[SysTable] +[SugarTable(null, "支付宝交易记录表")] +[SugarIndex("index_{table}_U", nameof(UserId), OrderByType.Asc)] +[SugarIndex("index_{table}_T", nameof(TradeNo), OrderByType.Asc)] +[SugarIndex("index_{table}_O", nameof(OutTradeNo), OrderByType.Asc)] +public class SysAlipayTransaction : EntityBase +{ + /// + /// 用户Id + /// + [SugarColumn(ColumnDescription = "用户Id", Length = 64)] + public long UserId { get; set; } + + /// + /// 交易号 + /// + [SugarColumn(ColumnDescription = "交易号", Length = 64)] + public string? TradeNo { get; set; } + + /// + /// 商户订单号 + /// + [SugarColumn(ColumnDescription = "商户订单号", Length = 64)] + public string OutTradeNo { get; set; } + + /// + /// 交易金额 + /// + [SugarColumn(ColumnDescription = "交易金额", Length = 20)] + public decimal TotalAmount { get; set; } + + /// + /// 交易状态 + /// + [SugarColumn(ColumnDescription = "交易状态", Length = 32)] + public string TradeStatus { get; set; } + + /// + /// 交易完成时间 + /// + [SugarColumn(ColumnDescription = "交易完成时间")] + public DateTime? FinishTime { get; set; } + + /// + /// 交易标题 + /// + [SugarColumn(ColumnDescription = "交易标题", Length = 256)] + public string Subject { get; set; } + + /// + /// 交易描述 + /// + [SugarColumn(ColumnDescription = "交易描述", Length = 512)] + public string? Body { get; set; } + + /// + /// 买家支付宝账号 + /// + [SugarColumn(ColumnDescription = "买家支付宝账号", Length = 128)] + public string? BuyerLogonId { get; set; } + + /// + /// 买家支付宝用户ID + /// + [SugarColumn(ColumnDescription = "买家支付宝用户ID", Length = 32)] + public string? BuyerUserId { get; set; } + + /// + /// 卖家支付宝用户ID + /// + [SugarColumn(ColumnDescription = "卖家支付宝用户ID", Length = 32)] + public string? SellerUserId { get; set; } + + /// + /// 商户AppId + /// + [SugarColumn(ColumnDescription = "商户AppId", Length = 64)] + public string? AppId { get; set; } + + /// + /// 交易扩展信息 + /// + [SugarColumn(ColumnDescription = "交易扩展信息", Length = 1024)] + public string? ExtendInfo { get; set; } + + /// + /// 交易异常信息 + /// + [SugarColumn(ColumnDescription = "交易扩展信息", Length = 1024)] + public string? ErrorInfo { get; set; } + + /// + /// 交易备注 + /// + [SugarColumn(ColumnDescription = "交易备注", Length = 512)] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Option/AlipayOptions.cs b/Admin.NET/Admin.NET.Core/Option/AlipayOptions.cs index 2ece6bb6..ddd1bb02 100644 --- a/Admin.NET/Admin.NET.Core/Option/AlipayOptions.cs +++ b/Admin.NET/Admin.NET.Core/Option/AlipayOptions.cs @@ -4,6 +4,8 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +using Aop.Api; + namespace Admin.NET.Core; /// @@ -12,57 +14,106 @@ namespace Admin.NET.Core; public sealed class AlipayOptions : IConfigurableOptions { /// - /// 支付宝 APPID(必填) + /// 支付宝网关地址 /// - public string AppId { get; set; } + public string ServerUrl { get; init; } /// - /// 支付宝 websocket 服务地址 (必填) + /// 支付宝授权回调地址 /// - public string AlipayWebsocketUrl { get; set; } + public string AuthUrl { get; init; } /// - /// 支付宝网关地址 (必填) + /// 应用授权回调地址 /// - public string ServerUrl { get; set; } + public string AppAuthUrl { get; init; } /// - /// 支付宝授权回调地址 (必填) + /// 支付宝 websocket 服务地址 /// - public string AuthUrl { get; set; } + public string WebsocketUrl { get; init; } /// /// 应用回调地址 /// - public string NotifyUrl { get; set; } + public string NotifyUrl { get; init; } /// - /// 加密算法(必填) + /// 支付宝根证书存放路径 /// - public string SignType { get; set; } + public string RootCertPath { get; init; } + + /// + /// 支付宝商户账号列表 + /// + public List AccountList { get; init; } + + /// + /// 获取支付宝客户端 + /// + /// + public DefaultAopClient GetClient(AlipayMerchantAccount account) + { + account = account ?? throw new Exception("未找到支付宝商户账号"); + string path = App.WebHostEnvironment.ContentRootPath; + return new DefaultAopClient(new AlipayConfig + { + Format = "json", + Charset = "UTF-8", + ServerUrl = ServerUrl, + AppId = account.AppId, + SignType = account.SignType, + PrivateKey = account.PrivateKey, + EncryptKey = account.EncryptKey, + RootCertPath = Path.Combine(path, RootCertPath), + AppCertPath = Path.Combine(path, account.AppCertPath), + AlipayPublicCertPath = Path.Combine(path, account.AlipayPublicCertPath) + }); + } +} + +/// +/// 支付宝商户账号信息 +/// +public class AlipayMerchantAccount +{ + /// + /// 配置Id + /// + public long Id { get; init; } + + /// + /// 商户名称 + /// + public string Name { get; init; } + + /// + /// 商户AppId + /// + public string AppId { get; init; } + + /// + /// 应用私钥 + /// + public string PrivateKey { get; init; } /// /// 从支付宝获取敏感信息时的加密密钥(可选) /// - public string EncryptKey { get; set; } + public string EncryptKey { get; init; } /// - /// 应用私钥 (必填) + /// 加密算法 /// - public string PrivateKey { get; set; } + public string SignType { get; init; } /// - /// 支付宝公钥证书存放路径(证书加签方式必填) + /// 应用公钥证书路径 /// - public string AlipayPublicCertPath { get; set; } + public string AppCertPath { get; init; } /// - /// 支付宝根证书存放路径(证书加签方式必填) + /// 支付宝公钥证书路径 /// - public string RootCertPath { get; set; } - - /// - /// 应用公钥证书存放路径(证书加签方式必填) - /// - public string AppCertPath { get; set; } + public string AlipayPublicCertPath { get; init; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Alipay/AlipayService.cs b/Admin.NET/Admin.NET.Core/Service/Alipay/AlipayService.cs deleted file mode 100644 index 90f3f409..00000000 --- a/Admin.NET/Admin.NET.Core/Service/Alipay/AlipayService.cs +++ /dev/null @@ -1,279 +0,0 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -using Aop.Api; -using Aop.Api.Domain; -using Aop.Api.Request; -using Aop.Api.Response; -using Aop.Api.Util; -using Microsoft.AspNetCore.Hosting; - -namespace Admin.NET.Core.Service; - -/// -/// 支付宝支付服务 🧩 -/// -[ApiDescriptionSettings(Order = 240)] -public class AlipayService : IDynamicApiController, ITransient -{ - private readonly IEnumerable _alipayNotifyList; - private readonly IWebHostEnvironment _webHostEnvironment; - private readonly SysConfigService _sysConfigService; - private readonly IHttpContextAccessor _httpContext; - private readonly AlipayOptions _alipayOptions; - private readonly IAopClient _alipayClient; - private readonly UserManager _userManager; - - public AlipayService( - UserManager userManager, - IHttpContextAccessor httpContext, - SysConfigService sysConfigService, - IWebHostEnvironment webHostEnvironment, - IOptions alipayOptions) - { - _userManager = userManager; - _httpContext = httpContext; - _sysConfigService = sysConfigService; - _alipayOptions = alipayOptions.Value; - _webHostEnvironment = webHostEnvironment; - _alipayNotifyList = App.GetServices(); - - // 初始化支付宝客户端 - string path = App.WebHostEnvironment.ContentRootPath; - _alipayClient = new DefaultAopClient(new AlipayConfig - { - Format = "json", - Charset = "UTF-8", - AppId = _alipayOptions.AppId, - SignType = _alipayOptions.SignType, - ServerUrl = _alipayOptions.ServerUrl, - PrivateKey = _alipayOptions.PrivateKey, - EncryptKey = _alipayOptions.EncryptKey, - AppCertPath = Path.Combine(path, _alipayOptions.AppCertPath), - RootCertPath = Path.Combine(path, _alipayOptions.RootCertPath), - AlipayPublicCertPath = Path.Combine(path, _alipayOptions.AlipayPublicCertPath) - }); - } - - /// - /// 获取授权信息 🔖 - /// - /// - /// - [NonUnify] - [AllowAnonymous] - [DisplayName("获取授权信息")] - [ApiDescriptionSettings(Name = "GetAuthInfo"), HttpGet] - public ActionResult GetAuthInfo([FromQuery] AlipayAuthInfoInput input) - { - var type = input.UserId.Split('-').FirstOrDefault().ToInt(); - var userId = input.UserId.Split('-').LastOrDefault().ToLong(); - - // 当前网页接口地址 - var currentUrl = $"{_httpContext.HttpContext!.Request.GetOrigin()}{_httpContext.HttpContext!.Request.Path}?userId={input.UserId}"; - if (string.IsNullOrEmpty(input.AuthCode)) - { - // 重新授权 - var url = $"{_alipayOptions.AuthUrl}?app_id={_alipayOptions.AppId}&scope=auth_user&redirect_uri={currentUrl}"; - return new RedirectResult(url); - } - - // 组装授权请求参数 - AlipaySystemOauthTokenRequest request = new() - { - GrantType = AlipayConst.GrantType, - Code = input.AuthCode - }; - AlipaySystemOauthTokenResponse response = _alipayClient.CertificateExecute(request); - - // token换取用户信息 - AlipayUserInfoShareRequest infoShareRequest = new(); - AlipayUserInfoShareResponse info = _alipayClient.CertificateExecute(infoShareRequest, response.AccessToken); - - // 循环执行扫码后需要执行的业务逻辑,需要至少一个继承方法返回true,否则抛出异常 - var pass = false; - foreach (var notify in _alipayNotifyList) - if (notify.ScanCallback(type, userId, info)) pass = true; - if (!pass) throw Oops.Oh("未处理的授权逻辑"); - - // 执行完,重定向到指定界面 - var authPageUrl = _sysConfigService.GetConfigValueByCode(ConfigConst.AlipayAuthPageUrl + type).Result; - return new RedirectResult(authPageUrl); - } - - /// - /// 支付回调 🔖 - /// - /// - [AllowAnonymous] - [DisplayName("支付回调")] - [ApiDescriptionSettings(Name = "Notify"), HttpPost] - public string Notify() - { - SortedDictionary sorted = []; - foreach (string key in _httpContext.HttpContext!.Request.Form.Keys) - sorted.Add(key, _httpContext.HttpContext.Request.Form[key]); - - string alipayPublicKey = Path.Combine(_webHostEnvironment.ContentRootPath, _alipayOptions.AlipayPublicCertPath!.Replace('/', '\\').TrimStart('\\')); - bool signVerified = AlipaySignature.RSACertCheckV1(sorted, alipayPublicKey, "UTF-8", _alipayOptions.SignType); // 调用SDK验证签名 - if (!signVerified) throw Oops.Oh("交易失败"); - - var outTradeNo = sorted.GetValueOrDefault("out_trade_no"); - try - { - // 记录回调日志 - File.AppendAllText($"{_webHostEnvironment.ContentRootPath}\\AlipayLog\\Notify-{DateTime.Today:yyyy-MM-dd}.txt", - $"支付宝支付到平台({DateTime.Now:yyyy-MM-dd HH:mm:ss}):{Environment.NewLine} " + - $"登录人:{_userManager.UserId}-{_userManager.RealName}{Environment.NewLine} " + - $"IP:{App.HttpContext?.GetRemoteIpAddressToIPv4(true)} {Environment.NewLine} " + - $"交易号:{outTradeNo}{Environment.NewLine} " + - $"参数:{JSON.Serialize(sorted)}{Environment.NewLine} " + - $"-----------------------------------------------------------------------------------------------------------------------" + - $"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}"); - } - catch (Exception ex) - { - Log.Error("支付宝支付回调日志写入失败:", ex); - } - - if (sorted.GetValueOrDefault(AlipayConst.TradeStatus) == AlipayConst.TradeSuccess) - { - // 约定交易码前四位为类型码,后面为订单号 - var tradeNo = long.Parse(outTradeNo); - var type = long.Parse(outTradeNo[..4]); - - // 循环执行业务逻辑,若都未处理(回调全部返回false)则交易失败 - var isError = true; - foreach (var notify in _alipayNotifyList) - if (notify.TopUpCallback(type, tradeNo)) isError = false; - if (isError) throw Oops.Oh("交易失败"); - } - return "success"; - } - - /// - /// 统一收单下单并支付页面接口 🔖 - /// - /// - /// - [DisplayName("统一收单下单并支付页面接口")] - [ApiDescriptionSettings(Name = "AlipayTradePagePay"), HttpPost] - public string AlipayTradePagePay(AlipayTradePagePayInput input) - { - AlipayTradeWapPayRequest request = new(); - - // 组装业务参数model - AlipayTradeWapPayModel model = new() - { - Subject = input.Subject, - OutTradeNo = input.OutTradeNo, - TotalAmount = input.TotalAmount, - Body = input.Body, - ProductCode = "QUICK_WAP_WAY", - TimeExpire = input.TimeoutExpress - }; - request.SetBizModel(model); - - // 设置异步通知接收地址 - request.SetNotifyUrl(_alipayOptions.NotifyUrl); - - var response = _alipayClient.SdkExecute(request); - if (response.IsError) throw Oops.Oh(response.SubMsg); - return $"{_alipayOptions.ServerUrl}?{response.Body}"; - } - - /// - /// 交易预创建 🔖 - /// - /// - /// - [DisplayName("交易预创建")] - [ApiDescriptionSettings(Name = "AlipayPreCreate"), HttpPost] - public string AlipayPreCreate(AlipayPreCreateInput input) - { - AlipayTradePrecreateRequest request = new(); - - // 设置异步通知接收地址 - request.SetNotifyUrl(_alipayOptions.NotifyUrl); - - // 组装业务参数model - AlipayTradePrecreateModel model = new() - { - Subject = input.Subject, - OutTradeNo = input.OutTradeNo, - TotalAmount = input.TotalAmount, - TimeoutExpress = input.TimeoutExpress - }; - request.SetBizModel(model); - - var response = _alipayClient.CertificateExecute(request); - if (response.IsError) throw Oops.Oh(response.SubMsg); - return response.QrCode; - } - - /// - /// 单笔转账到支付宝账户 - /// https://opendocs.alipay.com/open/62987723_alipay.fund.trans.uni.transfer - /// - [NonAction] - public Task Transfer(AlipayFundTransUniTransferInput input) - { - // 构造请求参数以调用接口 - AlipayFundTransUniTransferRequest request = new(); - AlipayFundTransUniTransferModel model = new() - { - BizScene = AlipayConst.BizScene, - ProductCode = AlipayConst.ProductCode, - - // 设置商家侧唯一订单号 - OutBizNo = input.OutBizNo, - - // 设置订单总金额 - TransAmount = input.TransAmount.ToString(), - - // 设置转账业务的标题 - OrderTitle = input.OrderTitle - }; - - // 设置收款方信息 - Participant payeeInfo = new() - { - CertType = input.CertType.ToString(), - CertNo = input.CertNo, - Identity = input.Identity, - Name = input.Name, - IdentityType = input.IdentityType.ToString() - }; - model.PayeeInfo = payeeInfo; - - // 设置业务备注 - model.Remark = input.Remark; - - // 设置转账业务请求的扩展参数 - string payerShowNameUseAlias = input.PayerShowNameUseAlias.ToString().ToLower(); - model.BusinessParams = $"{{\"payer_show_name_use_alias\":\"{payerShowNameUseAlias}\"}}"; - - request.SetBizModel(model); - var response = _alipayClient.CertificateExecute(request); - - try - { - File.AppendAllText($"{_webHostEnvironment.ContentRootPath}\\AlipayLog\\{DateTime.Today:yyyy-MM-dd}.txt", - $"支付宝付款到账户({DateTime.Now:yyyy-MM-dd HH:mm:ss}):{Environment.NewLine} " + - $"登录人:{_userManager.UserId}-{_userManager.RealName}{Environment.NewLine} " + - $"IP:{App.HttpContext?.GetRemoteIpAddressToIPv4(true)} {Environment.NewLine} " + - $"参数:{JSON.Serialize(model)}{Environment.NewLine} " + - $"返回:{JSON.Serialize(response)}{Environment.NewLine}" + - $"-----------------------------------------------------------------------------------------------------------------------" + - $"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}"); - } - catch (Exception ex) - { - Log.Error("单笔转账到支付宝账户日志写入失败:", ex); - } - return Task.FromResult(response); - } -} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Alipay/Dto/AlipayInput.cs b/Admin.NET/Admin.NET.Core/Service/Alipay/Dto/AlipayInput.cs index 03421b25..178daad1 100644 --- a/Admin.NET/Admin.NET.Core/Service/Alipay/Dto/AlipayInput.cs +++ b/Admin.NET/Admin.NET.Core/Service/Alipay/Dto/AlipayInput.cs @@ -4,28 +4,37 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +using System.Text.Json.Serialization; using Aop.Api.Domain; +using Newtonsoft.Json; namespace Admin.NET.Core.Service; public class AlipayFundTransUniTransferInput { /// - /// 商家侧唯一订单号 + /// 用户ID + /// + public long UserId { get; set; } + + /// + /// 商户AppId + /// + public string AppId { get; set; } + + /// + /// 商家订单号 /// - [Required(ErrorMessage = "订单号不能为空")] public string OutBizNo { get; set; } /// /// 转账金额 /// - [Required(ErrorMessage = "转账金额不能为空")] - public decimal? TransAmount { get; set; } + public decimal TransAmount { get; set; } /// - /// 转账业务标题 + /// 业务标题 /// - [Required(ErrorMessage = "业务标题不能为空")] public string OrderTitle { get; set; } /// @@ -46,25 +55,21 @@ public class AlipayFundTransUniTransferInput /// /// 收款方证件号码,条件必填 /// - [CommonValidation($"{nameof(CertType)} != null && string.IsNullOrWhiteSpace({nameof(CertNo)})", "", ErrorMessage = "证件号码不能为空")] public string CertNo { get; set; } /// /// 收款方身份标识 /// - [Required(ErrorMessage = "身份标识不能为空")] public string Identity { get; set; } /// /// 收款方真实姓名 /// - [Required(ErrorMessage = "真实姓名不能为空")] public string Name { get; set; } /// /// 收款方身份标识类型 /// - [Required(ErrorMessage = "身份标识类型不能为空")] public AlipayIdentityTypeEnum? IdentityType { get; set; } } @@ -159,10 +164,17 @@ public class AlipayAuthInfoInput /// /// 用户Id /// + + [JsonProperty("user_id")] + [JsonPropertyName("user_id")] + [FromQuery(Name = "user_id")] public string UserId { get; set; } /// /// 授权码 /// + [JsonProperty("auth_code")] + [JsonPropertyName("auth_code")] + [FromQuery(Name = "auth_code")] public string AuthCode { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Alipay/SysAlipayService.cs b/Admin.NET/Admin.NET.Core/Service/Alipay/SysAlipayService.cs new file mode 100644 index 00000000..e55af406 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/Alipay/SysAlipayService.cs @@ -0,0 +1,271 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Aop.Api; +using Aop.Api.Domain; +using Aop.Api.Request; +using Aop.Api.Response; +using Aop.Api.Util; +using Microsoft.AspNetCore.Hosting; +using NewLife.Reflection; + +namespace Admin.NET.Core.Service; + +/// +/// 支付宝支付服务 🧩 +/// +[ApiDescriptionSettings(Order = 240)] +public class SysAlipayService : IDynamicApiController, ITransient +{ + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly SysConfigService _sysConfigService; + private readonly List _alipayClientList; + private readonly IHttpContextAccessor _httpContext; + private readonly AlipayOptions _option; + private readonly ISqlSugarClient _db; + + public SysAlipayService( + ISqlSugarClient db, + IHttpContextAccessor httpContext, + SysConfigService sysConfigService, + IWebHostEnvironment webHostEnvironment, + IOptions alipayOptions) + { + _db = db; + _httpContext = httpContext; + _sysConfigService = sysConfigService; + _option = alipayOptions.Value; + _webHostEnvironment = webHostEnvironment; + + // 初始化支付宝客户端列表 + _alipayClientList = []; + foreach (var account in _option.AccountList) _alipayClientList.Add(_option.GetClient(account)); + } + + /// + /// 获取授权信息 🔖 + /// + /// + /// + [NonUnify] + [AllowAnonymous] + [DisplayName("获取授权信息")] + [ApiDescriptionSettings(Name = "AuthInfo"), HttpGet] + public ActionResult GetAuthInfo([FromQuery] AlipayAuthInfoInput input) + { + var type = input.UserId?.Split('-').FirstOrDefault().ToInt(); + var userId = input.UserId?.Split('-').LastOrDefault().ToLong(); + var account = _option.AccountList.FirstOrDefault(); + var alipayClient = _alipayClientList.First(); + + // 当前网页接口地址 + var currentUrl = $"{_option.AppAuthUrl}{_httpContext.HttpContext!.Request.Path}?userId={input.UserId}"; + if (string.IsNullOrEmpty(input.AuthCode)) + { + // 重新授权 + var url = $"{_option.AuthUrl}?app_id={account!.AppId}&scope=auth_user&redirect_uri={currentUrl}"; + return new RedirectResult(url); + } + + // 组装授权请求参数 + AlipaySystemOauthTokenRequest request = new() + { + GrantType = AlipayConst.GrantType, + Code = input.AuthCode + }; + AlipaySystemOauthTokenResponse response = alipayClient.CertificateExecute(request); + + // token换取用户信息 + AlipayUserInfoShareRequest infoShareRequest = new(); + AlipayUserInfoShareResponse info = alipayClient.CertificateExecute(infoShareRequest, response.AccessToken); + + // 记录授权信息 + var entity = _db.Queryable().First(u => + (!string.IsNullOrWhiteSpace(u.UserId) && u.UserId == info.UserId) || + (!string.IsNullOrWhiteSpace(u.OpenId) && u.OpenId == info.OpenId)) ?? new (); + entity.Copy(info, excludes: [nameof(SysAlipayAuthInfo.Gender), nameof(SysAlipayAuthInfo.Age)]); + entity.Age = int.Parse(info.Age); + entity.Gender = info.Gender switch + { + "m" => GenderEnum.Male, + "f" => GenderEnum.Female, + _ => GenderEnum.Unknown + }; + entity.AppId = account!.AppId; + if (entity.Id <= 0) _db.Insertable(entity).ExecuteCommand(); + else _db.Updateable(entity).ExecuteCommand(); + + // 执行完,重定向到指定界面 + //var authPageUrl = _sysConfigService.GetConfigValueByCode(ConfigConst.AlipayAuthPageUrl + type).Result; + //return new RedirectResult(authPageUrl); + return new RedirectResult(_option.AppAuthUrl + "/index.html"); + } + + /// + /// 支付回调 🔖 + /// + /// + [AllowAnonymous] + [DisplayName("支付回调")] + [ApiDescriptionSettings(Name = "Notify"), HttpPost] + public string Notify() + { + SortedDictionary sorted = []; + foreach (string key in _httpContext.HttpContext!.Request.Form.Keys) + sorted.Add(key, _httpContext.HttpContext.Request.Form[key]); + + var account = _option.AccountList.FirstOrDefault(); + string alipayPublicKey = Path.Combine(_webHostEnvironment.ContentRootPath, account!.AlipayPublicCertPath!.Replace('/', '\\').TrimStart('\\')); + bool signVerified = AlipaySignature.RSACertCheckV1(sorted, alipayPublicKey, "UTF-8", account.SignType); // 调用SDK验证签名 + if (!signVerified) throw Oops.Oh("交易失败"); + + // 更新交易记录 + var outTradeNo = sorted.GetValueOrDefault("out_trade_no"); + var transaction = _db.Queryable().First(x => x.OutTradeNo == outTradeNo) ?? throw Oops.Oh("交易记录不存在"); + transaction.TradeNo = sorted.GetValueOrDefault("trade_no"); + transaction.TradeStatus = sorted.GetValueOrDefault("trade_status"); + transaction.FinishTime = sorted.ContainsKey("gmt_payment") ? DateTime.Parse(sorted.GetValueOrDefault("gmt_payment")) : null; + transaction.BuyerLogonId = sorted.GetValueOrDefault("buyer_logon_id"); + transaction.BuyerUserId = sorted.GetValueOrDefault("buyer_user_id"); + transaction.SellerUserId = sorted.GetValueOrDefault("seller_id"); + transaction.Remark = sorted.GetValueOrDefault("remark"); + _db.Updateable(transaction).ExecuteCommand(); + + return "success"; + } + + /// + /// 统一收单下单并支付页面接口 🔖 + /// + /// + /// + [DisplayName("统一收单下单并支付页面接口")] + [ApiDescriptionSettings(Name = "AlipayTradePagePay"), HttpPost] + public string AlipayTradePagePay(AlipayTradePagePayInput input) + { + // 创建交易记录,状态为等待支付 + var transactionRecord = new SysAlipayTransaction + { + AppId = _option.AccountList.First().AppId, + OutTradeNo = input.OutTradeNo, + TotalAmount = input.TotalAmount.ToDecimal(), + TradeStatus = "WAIT_PAY", // 等待支付 + CreateTime = DateTime.Now, + Subject = input.Subject, + Body = input.Body, + Remark = "等待用户支付" + }; + _db.Insertable(transactionRecord).ExecuteCommand(); + + // 设置支付页面请求,并组装业务参数model,设置异步通知接收地址 + AlipayTradeWapPayRequest request = new(); + request.SetBizModel(new AlipayTradeWapPayModel() + { + Subject = input.Subject, + OutTradeNo = input.OutTradeNo, + TotalAmount = input.TotalAmount, + Body = input.Body, + ProductCode = "QUICK_WAP_WAY", + TimeExpire = input.TimeoutExpress + }); + request.SetNotifyUrl(_option.NotifyUrl); + + var alipayClient = _alipayClientList.First(); + var response = alipayClient.SdkExecute(request); + if (response.IsError) throw Oops.Oh(response.SubMsg); + return $"{_option.ServerUrl}?{response.Body}"; + } + + /// + /// 交易预创建 🔖 + /// + /// + /// + [DisplayName("交易预创建")] + [ApiDescriptionSettings(Name = "AlipayPreCreate"), HttpPost] + public string AlipayPreCreate(AlipayPreCreateInput input) + { + // 创建交易记录,状态为等待支付 + var transactionRecord = new SysAlipayTransaction + { + AppId = _option.AccountList.First().AppId, + OutTradeNo = input.OutTradeNo, + TotalAmount = input.TotalAmount.ToDecimal(), + TradeStatus = "WAIT_PAY", // 等待支付 + CreateTime = DateTime.Now, + Subject = input.Subject, + Remark = "等待用户支付" + }; + _db.Insertable(transactionRecord).ExecuteCommand(); + + // 设置异步通知接收地址,并组装业务参数model + AlipayTradePrecreateRequest request = new(); + request.SetNotifyUrl(_option.NotifyUrl); + request.SetBizModel(new AlipayTradePrecreateModel() + { + Subject = input.Subject, + OutTradeNo = input.OutTradeNo, + TotalAmount = input.TotalAmount, + TimeoutExpress = input.TimeoutExpress + }); + + var alipayClient = _alipayClientList.First(); + var response = alipayClient.CertificateExecute(request); + if (response.IsError) throw Oops.Oh(response.SubMsg); + return response.QrCode; + } + + /// + /// 单笔转账到支付宝账户 + /// https://opendocs.alipay.com/open/62987723_alipay.fund.trans.uni.transfer + /// + [NonAction] + public async Task Transfer(AlipayFundTransUniTransferInput input) + { + var account = _option.AccountList.FirstOrDefault(u => u.AppId == input.AppId) ?? throw Oops.Oh("未找到商户支付宝账号"); + var alipayClient = _option.GetClient(account); + + // 构造请求参数以调用接口 + AlipayFundTransUniTransferRequest request = new(); + AlipayFundTransUniTransferModel model = new() + { + BizScene = AlipayConst.BizScene, + ProductCode = AlipayConst.ProductCode, + OutBizNo = input.OutBizNo, // 商家订单 + TransAmount = $"{input.TransAmount}:F2", // 订单总金额 + OrderTitle = input.OrderTitle, // 业务标题 + Remark = input.Remark, // 业务备注 + PayeeInfo = new() // 收款方信息 + { + CertType = input.CertType?.ToString(), + CertNo = input.CertNo, + Identity = input.Identity, + Name = input.Name, + IdentityType = input.IdentityType.ToString() + }, + BusinessParams = input.PayerShowNameUseAlias ? "{\"payer_show_name_use_alias\":\"true\"}" : null + }; + + request.SetBizModel(model); + var response = alipayClient.CertificateExecute(request); + + // 保存转账记录 + await _db.Insertable(new SysAlipayTransaction + { + UserId = input.UserId, + AppId = input.AppId, + TradeNo = response.OrderId, + OutTradeNo = input.OutBizNo, + TotalAmount = response.Amount.ToDecimal(), + TradeStatus = response.Code == "10000" ? "SUCCESS" : "FAILED", + Subject = input.OrderTitle, + ErrorInfo = response.SubMsg, + Remark = input.Remark + }).ExecuteCommandAsync(); + + return response; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayPublicCert.crt b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayPublicCert.crt new file mode 100644 index 00000000..5ced5641 --- /dev/null +++ b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayPublicCert.crt @@ -0,0 +1,38 @@ +-----BEGIN CERTIFICATE----- +MIIDszCCApugAwIBAgIQICQSIl9wqwjbcsS1A/zPajANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE +BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjQxMjIyMTE0NzAzWhcNMjUxMjIyMTE0NzAzWjCB +hDELMAkGA1UEBhMCQ04xHzAdBgNVBAoMFm10cXdudzEyODlAc2FuZGJveC5jb20xDzANBgNVBAsM +BkFsaXBheTFDMEEGA1UEAww65pSv5LuY5a6dKOS4reWbvSnnvZHnu5zmioDmnK/mnInpmZDlhazl +j7gtMjA4ODcyMTA1MzI1NzEzMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIPs9UeN +0Hhp0qFTXE51E/a2EQ7YmMI8dJdBLWP17Irzo1I1Zxw3BIsrxEsdPJSGr76oQlunEyWYNyiVsOaL +6KE8V1FK6uPSJr5BK5W9o3wKg3XX7BKdflyB4964uRNJOOPpqNi4vwY1ZZFVpSHrZJ0ZAthDHGYo +o3/zdEEIwEWRkVAtMC6pJa8K0qk3qyaqHRMzwO3r13Ex8q/7+kO1iOsQ5UFQwKeV/g6/NuyEW9BZ +6y59BehHQBqf51ZJcPa91Dc6va/C6McKe/OWd+km9EFwjab0L2GvwdRtrxUAikR0tghgvx3fAfJw +nkfdjTzYUi/umDuVJlyW6xg0p9cJwLcCAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3 +DQEBCwUAA4IBAQAoaQR/LYaBNMQ9pjEAHNaLdheebL6TbDNI8thKYAhMKFfeJ4ZNZPwqg2FnCfhf +eVJctLqJtxgzzl0vazVGeFJRwrMvJXkZsU9veRjLP1s4QUOO5NqjxkDNuQnFnQZBsySLWkM/+0f3 +AcFImbXVUDuod/KnPZ6i2gbYNmaADAvYM8M87aqbvrfbLHBk6wtHR21l9MMu1BXyAlJn29k47xYj +XNRJo6292M4Y4fyGFxT7tC+kt+MA6WUTl4hB+PvuXJh26tUOEo6EcXAZekcDJNOLCioNTW9/ck4P +bj2Qxvouztndmd3zsT+flLiImEtGgRaClveKuUwrd9rzWLNkl2lw +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDszCCApugAwIBAgIQIBkIGbgVxq210KxLJ+YA/TANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UE +BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxJTAjBgNVBAsMHENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IHRlc3QxNjA0BgNVBAMMLUFudCBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgUjEgdGVzdDAeFw0xOTA4MTkxMTE2MDBaFw0yNDA4MDExMTE2MDBaMIGRMQswCQYDVQQGEwJD +TjEbMBkGA1UECgwSQW50IEZpbmFuY2lhbCB0ZXN0MSUwIwYDVQQLDBxDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSB0ZXN0MT4wPAYDVQQDDDVBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IENsYXNzIDIgUjEgdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMh4FKYO +ZyRQHD6eFbPKZeSAnrfjfU7xmS9Yoozuu+iuqZlb6Z0SPLUqqTZAFZejOcmr07ln/pwZxluqplxC +5+B48End4nclDMlT5HPrDr3W0frs6Xsa2ZNcyil/iKNB5MbGll8LRAxntsKvZZj6vUTMb705gYgm +VUMILwi/ZxKTQqBtkT/kQQ5y6nOZsj7XI5rYdz6qqOROrpvS/d7iypdHOMIM9Iz9DlL1mrCykbBi +t25y+gTeXmuisHUwqaRpwtCGK4BayCqxRGbNipe6W73EK9lBrrzNtTr9NaysesT/v+l25JHCL9tG +wpNr1oWFzk4IHVOg0ORiQ6SUgxZUTYcCAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3 +DQEBCwUAA4IBAQBWThEoIaQoBX2YeRY/I8gu6TYnFXtyuCljANnXnM38ft+ikhE5mMNgKmJYLHvT +yWWWgwHoSAWEuml7EGbE/2AK2h3k0MdfiWLzdmpPCRG/RJHk6UB1pMHPilI+c0MVu16OPpKbg5Vf +LTv7dsAB40AzKsvyYw88/Ezi1osTXo6QQwda7uefvudirtb8FcQM9R66cJxl3kt1FXbpYwheIm/p +j1mq64swCoIYu4NrsUYtn6CV542DTQMI5QdXkn+PzUUly8F6kDp+KpMNd0avfWNL5+O++z+F5Szy +1CPta1D7EQ/eYmMP+mOQ35oifWIoFCpN6qQVBS/Hob1J/UUyg7BW +-----END CERTIFICATE----- diff --git a/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayRootCert.crt b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayRootCert.crt new file mode 100644 index 00000000..d129c75e --- /dev/null +++ b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/alipayRootCert.crt @@ -0,0 +1,88 @@ +-----BEGIN CERTIFICATE----- +MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG +EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw +MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO +UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE +MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT +V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti +W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ +MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b +53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI +pDoiVhsLwg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE +BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0 +MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV +BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk +rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2 +xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp +dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6 +vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl +YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1 +Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H +DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98 +SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG +PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe +9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC +AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90 +tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy +nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf +tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq +JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3 +IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW +05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41 +T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI +kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop +PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N +1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y +jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02 +77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi +kT9qhqn+lw== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG +EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0 +WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE +CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp +YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU +WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt +rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ +4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2 +zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg +wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH +Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF +BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM +E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg +MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq +MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp +bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv +b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV +nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5 +4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg +wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw +WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN +z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g +KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA +uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp +emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3 +U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I +UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn +DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU +1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX +Yf4Zr0fJsGuv +-----END CERTIFICATE----- \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/appPublicCert.crt b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/appPublicCert.crt new file mode 100644 index 00000000..a6a89dfa --- /dev/null +++ b/Admin.NET/Admin.NET.Web.Entry/Alipaycrt/appPublicCert.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDmTCCAoGgAwIBAgIQICQSIV6QZN2y3Knbwe6r9TANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE +BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjQxMjIxMTEzOTMzWhcNMjUxMjI2MTEzOTMzWjBr +MQswCQYDVQQGEwJDTjEfMB0GA1UECgwWbXRxd253MTI4OUBzYW5kYm94LmNvbTEPMA0GA1UECwwG +QWxpcGF5MSowKAYDVQQDDCEyMDg4NzIxMDUzMjU3MTMyLTkwMjEwMDAxNDI2ODYzOTUwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxJhoamnjWZGQp+1kHXTyQgA2va0rTQv8ZvFggERZv +fOg2i5RYTBFLB0J1l3hj+23iBqzRTgzPxCLUTZUrj6WgwdDbXi11eE2wltVwmDHI1r3YdLC6KCQN +Jpv6SKSHs9JV6UDpzsHaJbsoi6NymYpkbFClLCh3MOcyha9Ju4B9n5mKze1GEDTNcAs1nGfSsH1E +wAWoe65iVM8pbTXTzjbEW/jJc2xbFT9RPRTihflkEf6p3kOpaPtgFmcUqdJ4BsldL6iWqbdR5JhT +mVKT8hDmsbW9KpPnCXWedxBZHmNiuOOCOeDhHGV3zFrZvIPJa7umAL+eweg0egN5RHP9tDAnAgMB +AAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEANPJelQG99aAZb+KXUE3Z +ES+ZjPD9WwCBWpfcjyDq6duEQc9Qo0B2vW6EunbOi2qhS0dJ3pgJFaRrbi72BqQavT1eVYHcfXeC +y8I3dI7oxn5BS944oiGTzaYTx6dJ8lXDmlQO8ULz+6/wBCkhr6TgKbjIOh7p3/B9NPcfL5z6OrbQ +fXRk439uRfjWlzohE9q4cAY5AYnHLZCgbHwRX+YusDmJCu+LS9hioNHjwJ9t/jXsjzEQ09sfzEHF +uPGKS4JGmzwqGp2Ly68MCzp7WOgEFBexYUio4suzKlZUcv1+HDi6fEosZ6Fr7Z3CEMwKelq8m2l7 +jg83G0PECp5unR1Hcw== +-----END CERTIFICATE----- \ No newline at end of file