😎增加支付宝支付

This commit is contained in:
zuohuaijun 2024-12-29 23:53:58 +08:00
parent 7eb18ed737
commit 681b8adb2f
26 changed files with 1711 additions and 19 deletions

View File

@ -0,0 +1,18 @@
{
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
// 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" //
}
}

View File

@ -14,9 +14,11 @@
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="3.1.0" />
<PackageReference Include="AlipaySDKNet.Standard" Version="4.9.370" />
<PackageReference Include="AngleSharp" Version="1.1.2" />
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" Aliases="BouncyCastleV2" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.16.3" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.6.20" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.6.20" />
@ -37,6 +39,7 @@
<PackageReference Include="MySqlBackup.NET.MySqlConnector" Version="2.3.8" />
<PackageReference Include="NewLife.Redis" Version="6.0.2024.1205" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="RabbitMQ.Client" Version="7.0.0" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.3" />
@ -58,7 +61,6 @@
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.11" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
@ -68,7 +70,6 @@
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.0" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,92 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 通用接口参数验证特性类
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class CommonValidationAttribute : ValidationAttribute
{
private readonly Dictionary<string, string> _conditions;
private static readonly Dictionary<string, Delegate> CompiledConditions = new();
/// <summary>
/// </summary>
/// <param name="conditionPairs">条件对参数,长度必须为偶数<br/>
/// 奇数字符串参数:动态条件<br/>
/// 偶数字符串参数:提示消息
/// </param>
/// <example>
/// <code lang="C">
/// public class ModelInput {
///
///
/// public string A { get; set; }
///
///
/// [CommonValidation(
/// "A == 1 <value>&amp;&amp;</value> B == null", "当 A == 1时B不能为空",
/// "C == 2 <value>&amp;&amp;</value> B == null", "当 C == 2时B不能为空"
/// )]
/// public string B { get; set; }
/// }
/// </code>
/// </example>
public CommonValidationAttribute(params string[] conditionPairs)
{
if (conditionPairs.Length % 2 != 0) throw new ArgumentException("条件对必须以偶数个字符串的形式提供。");
var conditions = new Dictionary<string, string>();
for (int i = 0; i < conditionPairs.Length; i += 2)
conditions.Add(conditionPairs[i], conditionPairs[i + 1]);
_conditions = conditions;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
foreach (var (expr, errorMessage) in _conditions)
{
var conditionKey = $"{validationContext.ObjectType.FullName}.{expr}";
if (!CompiledConditions.TryGetValue(conditionKey, out var condition))
{
condition = CreateCondition(validationContext.ObjectType, expr);
CompiledConditions[conditionKey] = condition;
}
if ((bool)condition.DynamicInvoke(validationContext.ObjectInstance)!)
{
return new ValidationResult(errorMessage ?? $"[{validationContext.MemberName}]校验失败");
}
}
return ValidationResult.Success;
}
private Delegate CreateCondition(Type modelType, string expression)
{
try
{
// 创建参数表达式
var parameter = Expression.Parameter(typeof(object), "x");
// 构建 Lambda 表达式
var lambda = DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(modelType, "x") }, typeof(bool), expression);
// 创建新的 Lambda 表达式,接受 object 参数并调用编译后的表达式
var invokeExpression = Expression.Invoke(lambda, Expression.Convert(parameter, modelType));
var finalLambda = Expression.Lambda<Func<object, bool>>(invokeExpression, parameter);
return finalLambda.Compile();
}
catch (Exception ex)
{
throw new ArgumentException($"无法解析表达式 '{expression}': {ex.Message}", ex);
}
}
}

View File

@ -0,0 +1,39 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 支付宝支付常量
/// </summary>
[SuppressSniffer]
public class AlipayConst
{
/// <summary>
/// 单笔无密转账【业务场景】固定值
/// </summary>
public const string BizScene = "DIRECT_TRANSFER";
/// <summary>
/// 单笔无密转账【销售产品码】固定值
/// </summary>
public const string ProductCode = "TRANS_ACCOUNT_NO_PWD";
/// <summary>
/// 交易状态参数名
/// </summary>
public const string TradeStatus = "trade_status";
/// <summary>
/// 交易成功标识
/// </summary>
public const string TradeSuccess = "TRADE_SUCCESS";
/// <summary>
/// 授权类型
/// </summary>
public const string GrantType = "authorization_code";
}

View File

@ -121,6 +121,11 @@ public class ConfigConst
/// </summary>
public const string SysUpgrade = "sys_upgrade";
/// <summary>
/// 支付宝授权页面地址
/// </summary>
public const string AlipayAuthPageUrl = "alipay_auth_page_url_";
/// <summary>
/// Default 分组
/// </summary>

View File

@ -0,0 +1,21 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 参与方的证件类型枚举
/// </summary>
[SuppressSniffer]
[Description("参与方的证件类型枚举")]
public enum AlipayCertTypeEnum
{
[Description("身份证")]
IDENTITY_CARD,
[Description("护照")]
PASSPORT
}

View File

@ -0,0 +1,21 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 参与方的标识类型枚举
/// </summary>
[SuppressSniffer]
[Description("参与方的标识类型枚举")]
public enum AlipayIdentityTypeEnum
{
[Description("支付宝用户UID")]
ALIPAY_USER_ID,
[Description("支付宝登录号")]
ALIPAY_LOGON_ID
}

View File

@ -4,6 +4,8 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System.Text.Json;
namespace Admin.NET.Core;
/// <summary>
@ -446,4 +448,16 @@ public static partial class ObjectExtension
}
}
}
/// <summary>
/// 对象深复制
/// </summary>
/// <typeparam name="T">深复制源对象</typeparam>
/// <param name="obj">对象</param>
/// <returns></returns>
public static T DeepCopy<T>(this T obj)
{
var json = JsonSerializer.Serialize(obj);
return JsonSerializer.Deserialize<T>(json);
}
}

View File

@ -0,0 +1,68 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 支付宝支付配置选项
/// </summary>
public sealed class AlipayOptions : IConfigurableOptions
{
/// <summary>
/// 支付宝 APPID必填
/// </summary>
public string AppId { get; set; }
/// <summary>
/// 支付宝 websocket 服务地址 (必填)
/// </summary>
public string AlipayWebsocketUrl { get; set; }
/// <summary>
/// 支付宝网关地址 (必填)
/// </summary>
public string ServerUrl { get; set; }
/// <summary>
/// 支付宝授权回调地址 (必填)
/// </summary>
public string AuthUrl { get; set; }
/// <summary>
/// 应用回调地址
/// </summary>
public string NotifyUrl { get; set; }
/// <summary>
/// 加密算法(必填)
/// </summary>
public string SignType { get; set; }
/// <summary>
/// 从支付宝获取敏感信息时的加密密钥(可选)
/// </summary>
public string EncryptKey { get; set; }
/// <summary>
/// 应用私钥 (必填)
/// </summary>
public string PrivateKey { get; set; }
/// <summary>
/// 支付宝公钥证书存放路径(证书加签方式必填)
/// </summary>
public string AlipayPublicCertPath { get; set; }
/// <summary>
/// 支付宝根证书存放路径(证书加签方式必填)
/// </summary>
public string RootCertPath { get; set; }
/// <summary>
/// 应用公钥证书存放路径(证书加签方式必填)
/// </summary>
public string AppCertPath { get; set; }
}

View File

@ -0,0 +1,143 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 支付宝支付错误码
/// </summary>
public class AlipayErrorCode
{
/// <summary>
/// 错误代码
/// </summary>
public string Code { get; private set; }
/// <summary>
/// 错误消息
/// </summary>
public string Message { get; private set; }
/// <summary>
/// 解决方案
/// </summary>
public string Solution { get; private set; }
/// <summary>
/// 错误码集
/// </summary>
private static readonly List<AlipayErrorCode> StatusCodes = new()
{
new AlipayErrorCode { Code="SYSTEM_ERROR", Message="系统繁忙", Solution="可能是由于网络或者系统故障,请与技术人员联系以解决该问题。" },
new AlipayErrorCode { Code="INVALID_PARAMETER", Message="参数有误或没有参数", Solution="请检查并确认查询请求参数合法性。" },
new AlipayErrorCode { Code="AUTHORISE_NOT_MATCH", Message="授权失败,无法获取用户信息", Solution="检查账户与支付方关系主表关系,确认是否正确配置。" },
new AlipayErrorCode { Code="BALANCE_IS_NOT_ENOUGH", Message="余额不足,建议尽快充值。后续登录电银通或支付宝,自主设置余额预警提醒功能。", Solution="余额不足建议尽快充值。商户后续登录电银通或支付宝自主设置余额预警提醒功能或登录Alipay-资金管理->产品一览->右上角功能按钮进行设置。" },
new AlipayErrorCode { Code="BIZ_UNIQUE_EXCEPTION", Message="商户订单号冲突。", Solution="商户订单号冲突。" },
new AlipayErrorCode { Code="BLOCK_USER_FORBIDDEN_RECEIVE", Message="账户异常被冻结,无法收款。", Solution="账户异常被冻结无法收款。请询问支付宝热线95188" },
new AlipayErrorCode { Code="BLOCK_USER_FORBIDDEN_SEND", Message="该账户被冻结,暂不可将资金转出。", Solution="该账户被冻结,暂不可将资金转出。" },
new AlipayErrorCode { Code="CURRENCY_NOT_SUPPORT", Message="币种不支持", Solution="请查询您的结算币种需求所见币种,目前限于人民币/美元结算。" },
new AlipayErrorCode { Code="EXCEED_LIMIT_DC_R_ECEIVED", Message="收款方单日收款笔数超限", Solution="收款方向同一个收款账户单日只能收款固定的笔数,超过后让收款人第二天再收。" },
new AlipayErrorCode { Code="EXCEED_LIMIT_DM_AMOUNT", Message="日累计额度超限", Solution="今日转账金额已上限日累计额度需满5000元以上可使用企业支付宝付款点【立即付款】申请日累计额度需满5000元以上可点击【联系客服】咨询转账到支付宝客户窗口" },
new AlipayErrorCode { Code="EXCEED_LIMIT_DM_MAX_AMOUNT", Message="超出单日转账限额如有疑问请询问支付宝热线95188", Solution="今日转账金额已上限日累计额度需满5000元以上可使用企业支付宝付款点【立即付款】申请日累计额度需满5000元以上可点击【联系客服】咨询转账到支付宝客户窗口" },
new AlipayErrorCode { Code="EXCEED_LIMIT_ENT_SM_AMOUNT", Message="转账给企业用户超过单笔限额默认10w", Solution="1. 10w以下的快速转账给企业用户。2. 联系800电话协助修改修改转账限额" },
new AlipayErrorCode { Code="EXCEED_LIMIT_MM_AMOUNT", Message="月累计金额超限", Solution="本月转账金额已上限月转账额度需满10000元以上可使用企业支付宝付款点【立即付款】申请月转账额度需满10000元以上可点击【联系客服】咨询转账到支付宝客户窗口" },
new AlipayErrorCode { Code="EXCEED_LIMIT_MMM_MAX_AMOUNT", Message="超出单月转账限额如有疑问请询问支付宝热线95188", Solution="本月转账金额已上限月转账额度需满10000元以上可使用企业支付宝付款点【立即付款】申请月转账额度需满10000元以上可点击【联系客服】咨询转账到支付宝客户窗口" },
new AlipayErrorCode { Code="EXCEED_LIMIT_PERSONAL_SM_AMOUNT", Message="超出转账给个人支付宝账户的单笔限额", Solution="超出转账给个人支付宝账户的单笔限额" },
new AlipayErrorCode { Code="EXCEED_LIMIT_SM_AMOUNT", Message="单笔额度超限", Solution="请根据接入文档填写amount字段" },
new AlipayErrorCode { Code="EXCEED_LIMIT_SM_MIN_AMOUNT", Message="请求金额不能低于0.1元", Solution="请修改转账金额。" },
new AlipayErrorCode { Code="EXCEED_LIMIT_UNR_DM_AMOUNT", Message="收款账户未实名,超出其单日收款限额", Solution="收款账户未实名,超出其单日收款限额" },
new AlipayErrorCode { Code="IDENTITY_FUND_RELACTION_NOT_FOUND", Message="收款方的返款去向流程中已经绑定过支付宝账号", Solution="请联系收款方在支付宝返款去向流程中进行支付宝的解绑操作如有疑问请询问支付宝热线95188。" },
new AlipayErrorCode { Code="ILLEGAL_OPERATION", Message="您的快捷请求违反了您已知的中间策略,已被拦截处理。请直接联系收款客户信息再次发起交易。", Solution="您的快捷请求违反了您已知的中间策略,已被拦截处理。请直接联系收款客户信息再次发起交易。" },
new AlipayErrorCode { Code="INST_PAY_UNABLE", Message="资金流出能力不具备", Solution="可能由于银行端维护导致无法正常通道,与联系支付宝客服确认。" },
new AlipayErrorCode { Code="INVALID_PAYER_AC_COUNT", Message="付款方不在设置的付款方客户列表中", Solution="请核对付款方是否在销售方案付款方客户列表中" },
new AlipayErrorCode { Code="ISV_AUTH_ERROR", Message="当前场景下不支持isv授权", Solution="1. 检查商户产品和场景范围当前场景下不支持isv授权权。2. 去删除isv授权模板改为自调用。" },
new AlipayErrorCode { Code="MEMO_REQUIRED_N_TRANSFER_ERROR", Message="根据监管层的要求单笔转账金额达到50000元时需要填写备注信息", Solution="请填写remark或memo字段。" },
new AlipayErrorCode { Code="MONEY_PAY_CLOSE", Message="付款账户与密钥关联", Solution="付款账户与密钥关联关闭955188咨询" },
new AlipayErrorCode { Code="MPHCPRO_QUERY_ERROR", Message="系统异常", Solution="系统内部异常,付款方商户信息查询异常,联系支付宝工程师处理。" },
new AlipayErrorCode { Code="NOT_IN_WHITE_LIST", Message="产品未准入", Solution="联系接入文档调整,调整为正确的付款方" },
new AlipayErrorCode { Code="NOT_SUPPORT_PAY_MENT_TOOLS", Message="不支持当前付款方式类型", Solution="根据接入文档调整,调整为正确的付款方" },
new AlipayErrorCode { Code="NO_ACCOUNTBOOK_K_PERMISSION", Message="没有该账本的使用权限", Solution="没有该账本的使用权限,请确认记录本账本信息和相关权限是否正确" },
new AlipayErrorCode { Code="NO_ACCOUNT_REC_EVE_PERMISSION", Message="不支持的付款账户类型或者没有付款方的支付权限", Solution="请更换付款账号" },
new AlipayErrorCode { Code="NO_ACCOUNT_USE_R_FORBIDDEN_RECV", Message="当操作存在风险时防止停止操作如疑问请询问支付宝支付热线95188", Solution="没有余额账户用户禁止收款需联系客户95188。" },
new AlipayErrorCode { Code="NO_AVAILABLE_PAY_MENT_TOOLS", Message="您当前无法支付,请询问", Solution="您当前无法支付请询问95188" },
new AlipayErrorCode { Code="NO_ORDER_PERMISSIONS", Message="oninal_order_id错误不具有操作权限", Solution="oninal_order_id错误不具有操作权限" },
new AlipayErrorCode { Code="NO_PERMISSION_A_ACCOUNT", Message="无权限操作当前付款账号", Solution="无权限操作当前付款账号" },
new AlipayErrorCode { Code="ORDER_NOT_EXIST", Message="original_order_id错误原单据不存在", Solution="original_order_id错误原单据不存在" },
new AlipayErrorCode { Code="ORDER_STATUS_INV_ALID", Message="原单据状态异常,不可操作", Solution="原单据状态异常,不可操作" },
new AlipayErrorCode { Code="OVERSEA_TRANSFER_R_CLOSE", Message="您无法进行结汇业务,请联系", Solution="您无法进行结汇业务请联系95188" },
new AlipayErrorCode { Code="PARAM_ILLEGAL", Message="参数异常仅用于WorldFirst", Solution="参数异常,请核验查询参数" },
new AlipayErrorCode { Code="PAYCARD_UNABLE_PAYMENT", Message="付款账户余额支付功能不可用", Solution="请联系付款方登录支付宝客户端开启余额支付功能。" },
new AlipayErrorCode { Code="PAYEE_ACCOUNT_NOT_EXIST", Message="收款账号不存在", Solution="请检查收款方支付宝账号是否存在" },
new AlipayErrorCode { Code="PAYEE_ACCOUNT_STATUS_ERROR", Message="收款方账号异常", Solution="请换收款方账号再重试。" },
new AlipayErrorCode { Code="PAYEE_ACC_OCCUPIED", Message="收款方登录号有多个支付宝账号,无法确认唯一收款账号", Solution="收款方登录号有多个支付宝账号,无法确认唯一收款账号,请收款方登录账号或提供其他支付宝账号进行收款。" },
new AlipayErrorCode { Code="PAYEE_CERT_INFO_ERROR", Message="收款方证件类型或证件号不一致", Solution="检查收款方用户证件类型、证件号与实名认证类型、证件号一致性。" },
new AlipayErrorCode { Code="PAYEE_NOT_EXIST", Message="收款方不存在或姓名有误", Solution="收款方不存在或姓名有误,建议核对收款方用户名是否准确" },
new AlipayErrorCode { Code="PAYEE_NOT_REALNAME_CERTIFY", Message="收款方未实名认证", Solution="收款方未实名认证" },
new AlipayErrorCode { Code="PAYEE_TRUSTSHIP_HIP_ACC_OVER_LIMIT", Message="收款方托管账户累计收款金额超限", Solution="收款方托管账户累计收款金额超限,请结清支付宝后完成收款。" },
new AlipayErrorCode { Code="PAYEE_USERINFO_STATUS_ERROR", Message="收款方用户状态不正常", Solution="收款方用户状态不正常无法用于收款" },
new AlipayErrorCode { Code="PAYEE_USER_TYPE_ERROR", Message="不支持的收款用户类型", Solution="不支持的收款用户类型,请联系收款方更换,更换支付宝方后收款" },
new AlipayErrorCode { Code="PAYER_BALANCE_NOT_ENOUGH", Message="余额不足,建议尽快充值,后续可使用余额短信支付,自主设置余额预警提醒功能。", Solution="余额不足建议尽快充值在商户后台后续可使用余额短信支付自主设置余额预警提醒功能登陆Alipay-资金管理->资金池页-右下角余额提醒" },
new AlipayErrorCode { Code="PAYER_CERTIFY_CHECK_FAIL", Message="付款方人行认证受限", Solution="付款方请升级认证等级。" },
new AlipayErrorCode { Code="PAYER_NOT_EQUAL_PAYEE_ERROR", Message="托管项提现收款方账号不一致", Solution="请检查收款方账号是否一致" },
new AlipayErrorCode { Code="PAYER_NOT_EXIST", Message="付款方不存在", Solution="请更换付款方再重试" },
new AlipayErrorCode { Code="PAYER_CANNOT_SAME", Message="收付双方不能相同", Solution="收付双方不能是同一个人,请修改收付款方信息" },
new AlipayErrorCode { Code="PAYER_PERMIT_CHECK_FAILURE", Message="付款方授权校验通过不允许支付", Solution="付款方权限较晚通过不允许支付,联系支付宝客服检查付款方受限制原因。" },
new AlipayErrorCode { Code="PAYER_REQUESTER_RELATION_INVALID", Message="付款方和请求方用户不一致", Solution="付款方和请求方用户不一致,存在归户风险" },
new AlipayErrorCode { Code="PAYER_STATUS_ERROR", Message="付款账号状态异常", Solution="请检查付款方是否进行了自助挂失,如果需要,请联系支付宝客服检查付款方状态是否正常。" },
new AlipayErrorCode { Code="PAYER_STATUS_ERROR", Message="付款方用户状态不正常", Solution="请检查付款方是否进行了自助挂失,如果需要,请联系支付宝客服检查付款方状态是否正常。" },
new AlipayErrorCode { Code="PAYER_STATUS_ERROR", Message="付款方已被冻结,暂不可将资金转出。", Solution="1. 联系支付宝客户询问用户冻结原因以及协助解冻办法状态。" },
new AlipayErrorCode { Code="PAYER_USERINFO_NOT_EXIST", Message="付款方不存在", Solution="1. 检查付款方是否已销户若销户请联系销户后重新发起业务。2. 检查参入是否有误。" },
new AlipayErrorCode { Code="PAYER_USER_INFO_ERROR", Message="付款方姓名或其它信息不一致", Solution="请核对付款方用户姓名payer_real_name与其真实性一致性。" },
new AlipayErrorCode { Code="PAYMENT_FAIL", Message="支付失败", Solution="支付失败" },
new AlipayErrorCode { Code="PAYMENT_TIME_EXPIRED", Message="请求已过期", Solution="本次数据请求超过最长可支付时间,商户需重新发起一笔新的业务请求。" },
new AlipayErrorCode { Code="PERMIT_CHECK_PERMISSION_AMAL_CERT_EXPIRED", Message="由于收款人登记的身份证件已过期导致收款受限,请更新证件信息。", Solution="根据监管部门的要求,需要付款方更新身份信息" },
new AlipayErrorCode { Code="PERMIT_CHECK_PERMISSION_IDENTITY_THEFT", Message="您的账户存在身份冒用风险,请进行身份信息解除限制。", Solution="您的账户存在身份冒用风险,请进行身份信息解除限制。" },
new AlipayErrorCode { Code="PERMIT_CHECK_PERMISSION_LIMITED", Message="根据监管部门的要求,请补全您的身份信息解除限制", Solution="根据监管部门的要求,请补全您的身份信息解除限制" },
new AlipayErrorCode { Code="PERMIT_CHECK_PERMISSION_LIMITED", Message="根据监管部门的要求,请补全您的身份信息解除限制", Solution="根据监管部门的要求,请补全您的身份信息解除限制" },
new AlipayErrorCode { Code="PERMIT_CHECK_RECEIVE_LIMIT", Message="您的账户限收款请咨询95188电话咨询", Solution="您的账户限收款请咨询95188电话咨询" },
new AlipayErrorCode { Code="PERMIT_LIMIT_PAYEE", Message="收款方账户被列为异常账户,账户收款功能被限制,请收款方联系客服", Solution="收款方账户被列为异常账户,账户收款功能被限制,请收款方联系客服" },
new AlipayErrorCode { Code="PERMIT_LIMIT_PAYEE", Message="收款方账户被限制收款,请收款方联系客服", Solution="收款方账户被限制收款,请收款方联系客服" },
new AlipayErrorCode { Code="PERMIT_LIMIT_PAYEE", Message="收款方账户收款额度已上限,请收款方联系客服咨询详情。", Solution="收款方账户收款额度已上限,请收款方联系客服咨询详情。" },
new AlipayErrorCode { Code="PERMIT_LIMIT_PAYEE", Message="收款方账户收款功能暂时无法使用", Solution="收款方账户收款功能暂时无法使用" },
new AlipayErrorCode { Code="PERMIT_NOT_BANK_LIMIT_PAYEE", Message="收款方未完善身份证信息或未开立余额账户,无法收款", Solution="根据监管部门的要求,收款方未完善身份证信息或未开立余额账户,无法收款" },
new AlipayErrorCode { Code="PERMIT_NOT_BANK_LIMIT_PAYEE", Message="当前操作存在风险不支持转账如无疑问请拨打支付宝服务热线95188", Solution="根据监管部门的要求,收款方未完善身份证信息或未开立余额账户,无法收款" },
new AlipayErrorCode { Code="PERMIT_PAYER_FORBIDDEN", Message="根据监管部门的要求,需要收款方补充身份信息才能继续操作", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PERMIT_PAYER_FORBIDDEN", Message="根据监管部门的要求,需要收款方补充身份信息才能继续操作", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PERM_PAY_CUSTOM_ER_DAILY_QUOTA_ORG_BALANCE_LIMIT", Message="同一主体下今日余额付款额度已上限。", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PERM_PAY_CUSTOM_ER_MONTH_QUOTA_ORG_BALANCE_LIMIT", Message="同一主体下当月余额付款额度已上限。", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PERM_PAY_USER_DAILY_QUOTA_ORG_BALANCE_LIMIT", Message="该账户今日余额付款额度已达上限。", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PERM_PAY_USER_MONTH_QUOTA_ORG_BALANCE_LIMIT", Message="该账户当月余额付款额度已达上限。", Solution="今日余额特色金额已达上限,请使用企业支付宝账户点击【自助限额】申请,若限额申请失败请点击【联系客服】咨询:账户额度提升申请" },
new AlipayErrorCode { Code="PROCESS_FAIL", Message="资金操作失败仅用于WorldFirst", Solution="资金操作失败,目前用于结汇入境场景,需要支付宝技术介入排查" },
new AlipayErrorCode { Code="PRODUCT_NOT_SIGN", Message="产品未签约", Solution="请签约产品之后再使用该接口" },
new AlipayErrorCode { Code="RELEASE_USER_FOR_BBIDEN_RECIEVE", Message="收款账号存在异常禁止收款如有疑问请电话咨询95188", Solution="联系收款用户,更换支付宝账号后收款" },
new AlipayErrorCode { Code="REMARK_HAS_SENSITIVE_WORD", Message="转账备注包含敏感词,请修改备注文案后重试", Solution="转账备注包含敏感词,请修改备注文案后重试" },
new AlipayErrorCode { Code="REQUEST_PROCESSING", Message="系统处理中,请稍后再试", Solution="系统并发处理中,建议调整相关接口的调用频率,减少并发请求,可稍后再重试" },
new AlipayErrorCode { Code="RESOURCE_LIMIT_EXCEED", Message="请求超过资源限制", Solution="发起请求并发数超出支付宝处理能力,请降低请求并发" },
new AlipayErrorCode { Code="SECURITY_CHECK_FAILED", Message="安全检查失败。当前操作存在风险请停止操作如有疑问请咨询服务热线95188", Solution="安全检查失败。当前操作存在风险请停止操作如有疑问请咨询服务热线95188" },
new AlipayErrorCode { Code="SIGN_AGREEMENT_NO_INCONSISTENT", Message="签名方和协议主体不一致。请确认payer_info.ext_info.agreement_no和sign_data.ori_app_id是否匹配。", Solution="签名方和协议主体不一致。请确认payer_info.ext_info.agreement_no和sign_data.ori_app_id是否匹配再重试。" },
new AlipayErrorCode { Code="SIGN_INVALID", Message="签名非法,验签不通过。请确认签名信息是否被篡改以及签名方签名格式是否正确。", Solution="签名非法,验签不通过。请确认签名信息是否被篡改以及签名方签名格式是否正确。" },
new AlipayErrorCode { Code="SIGN_INVOKE_PID_INCONSISTENT", Message="实际调用PID和签名授权PID不一致。请确认实际调用PID和sign_data.partner_id是否一致。", Solution="请确认实际调用PID和sign_data.partner_id是否一致一致后再重试。" },
new AlipayErrorCode { Code="SIGN_NOT_ALLOW_SKIP", Message="该场景强制验签不允许跳过。请按要求上报sign_data后重试。", Solution="该场景强制验签不允许跳过。请按要求上报sign_data后重试。" },
new AlipayErrorCode { Code="SIGN_PARAM_INVALID", Message="验签参数非法。请确认sign_data参数是否正确。", Solution="验签参数非法请确认sign_data参数是否正确。" },
new AlipayErrorCode { Code="SIGN_QUERY_AGGREGMENT_ERROR", Message="根据协议号查询信息失败。请确认payer_info.ext_info.agreement_no是否正确。", Solution="请确认上报协议号payer_info.ext_info.agreement_no内容正确后再重试。" },
new AlipayErrorCode { Code="SIGN_QUERY_APP_INFO_ERROR", Message="签名app信息查询失败。请确认sign_data.ori_app_id是否正确。", Solution="请确认签名方sign_data.ori_app_id是否正确信息正确后再重试。" },
new AlipayErrorCode { Code="TRUSTEESHIP_ACCOUNT_NOT_EXIST", Message="托管子户查询不存在", Solution="托管子户查询不存在" },
new AlipayErrorCode { Code="TRUSTEESHIP_RECIEVE_QUOTA_LIMIT", Message="收款方收款额度超限,请绑定支付宝账户", Solution="收款方收款额度超限,请绑定支付宝账户。" },
new AlipayErrorCode { Code="USER_AGREEMENT_VERIFY_FAIL", Message="用户协议校验失败", Solution="确认入参中协议号是否正确" },
new AlipayErrorCode { Code="USER_NOT_EXIST", Message="用户不存在仅用于WorldFirst", Solution="用户不存在,请检查收付款方信息" },
new AlipayErrorCode { Code="USER_RISK_FREEZE", Message="账户异常被冻结无法付款请咨询支付宝客服95188", Solution="账户异常被冻结无法付款请咨询支付宝客服95188" }
};
/// <summary>
/// 根据错误码获取错误信息
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static AlipayErrorCode Get(string code)
{
return StatusCodes.FirstOrDefault(u => u.Code.EqualIgnoreCase(code));
}
}

View File

@ -0,0 +1,273 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core.Service.Alipay;
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;
/// <summary>
/// 支付宝支付服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 240)]
public class AlipayService : IDynamicApiController, ITransient
{
private readonly UserManager _userManager;
private readonly SysConfigService _sysConfigService;
private readonly AlipayOptions _alipayOptions;
private readonly IHttpContextAccessor _httpContext;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IAopClient _alipayClient;
public AlipayService(UserManager userManager,
SysConfigService sysConfigService,
IOptions<AlipayOptions> alipayOptions,
IHttpContextAccessor httpContext,
IWebHostEnvironment webHostEnvironment)
{
_userManager = userManager;
_sysConfigService = sysConfigService;
_alipayOptions = alipayOptions.Value;
_httpContext = httpContext;
_webHostEnvironment = webHostEnvironment;
// 初始化支付宝客户端
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)
});
}
/// <summary>
/// 获取授权信息 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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 App.GetServices<IAlipayNotify>())
if (notify.ScanCallback(type, userId, info)) pass = true;
if (!pass) throw Oops.Oh("未处理的授权逻辑");
// 执行完,重定向到指定界面
var authPageUrl = _sysConfigService.GetConfigValueByCode<string>(ConfigConst.AlipayAuthPageUrl + type).Result;
return new RedirectResult(authPageUrl);
}
/// <summary>
/// 支付回调 🔖
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[DisplayName("支付回调")]
[ApiDescriptionSettings(Name = "Notify"), HttpPost]
public string Notify()
{
SortedDictionary<string, string> sorted = new();
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.Substring(0, 4));
// 循环执行业务逻辑,若都未处理(回调全部返回false)则交易失败
var isError = true;
foreach (var notify in App.GetServices<IAlipayNotify>())
if (notify.TopUpCallback(type, tradeNo)) isError = false;
if (isError) throw Oops.Oh("交易失败");
}
return "success";
}
/// <summary>
/// 统一收单下单并支付页面接口 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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}";
}
/// <summary>
/// 交易预创建 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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;
}
/// <summary>
/// 单笔转账到支付宝账户
/// https://opendocs.alipay.com/open/62987723_alipay.fund.trans.uni.transfer
/// </summary>
[NonAction]
public Task<AlipayFundTransUniTransferResponse> Transfer(AlipayFundTransUniTransferInput input)
{
// 构造请求参数以调用接口
AlipayFundTransUniTransferRequest request = new();
AlipayFundTransUniTransferModel model = new();
model.BizScene = AlipayConst.BizScene;
model.ProductCode = AlipayConst.ProductCode;
// 设置商家侧唯一订单号
model.OutBizNo = input.OutBizNo;
// 设置订单总金额
model.TransAmount = input.TransAmount.ToString();
// 设置转账业务的标题
model.OrderTitle = input.OrderTitle;
// 设置收款方信息
Participant payeeInfo = new();
payeeInfo.CertType = input.CertType.ToString();
payeeInfo.CertNo = input.CertNo;
payeeInfo.Identity = input.Identity;
payeeInfo.Name = input.Name;
payeeInfo.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);
}
}

View File

@ -0,0 +1,169 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Aop.Api.Domain;
using Newtonsoft.Json;
namespace Admin.NET.Core.Service;
public class AlipayFundTransUniTransferInput
{
/// <summary>
/// 商家侧唯一订单号
/// </summary>
[Required(ErrorMessage = "订单号不能为空")]
public string OutBizNo { get; set; }
/// <summary>
/// 转账金额
/// </summary>
[Required(ErrorMessage = "转账金额不能为空")]
public decimal? TransAmount { get; set; }
/// <summary>
/// 转账业务标题
/// </summary>
[Required(ErrorMessage = "业务标题不能为空")]
public string OrderTitle { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 是否展示付款方别名
/// </summary>
public bool PayerShowNameUseAlias { get; set; }
/// <summary>
/// 收款方证件类型
/// </summary>
public AlipayCertTypeEnum? CertType { get; set; }
/// <summary>
/// 收款方证件号码,条件必填
/// </summary>
[CommonValidation($"{nameof(CertType)} != null && string.IsNullOrWhiteSpace({nameof(CertNo)})", "", ErrorMessage = "证件号码不能为空")]
public string CertNo { get; set; }
/// <summary>
/// 收款方身份标识
/// </summary>
[Required(ErrorMessage = "身份标识不能为空")]
public string Identity { get; set; }
/// <summary>
/// 收款方真实姓名
/// </summary>
[Required(ErrorMessage = "真实姓名不能为空")]
public string Name { get; set; }
/// <summary>
/// 收款方身份标识类型
/// </summary>
[Required(ErrorMessage = "身份标识类型不能为空")]
public AlipayIdentityTypeEnum? IdentityType { get; set; }
}
/// <summary>
/// 统一收单下单并支付页面接口输入参数
/// </summary>
public class AlipayTradePagePayInput
{
/// <summary>
/// 商户订单号
/// </summary>
[Required(ErrorMessage = "商户订单号不能为空")]
public string OutTradeNo { get; set; }
/// <summary>
/// 订单总金额
/// </summary>
[Required(ErrorMessage = "订单总金额不能为空")]
public string TotalAmount { get; set; }
/// <summary>
/// 订单标题
/// </summary>
[Required(ErrorMessage = "订单标题不能为空")]
public string Subject { get; set; }
/// <summary>
///
/// </summary>
public string Body { get; set; }
/// <summary>
/// 超时时间
/// </summary>
public string TimeoutExpress { get; set; }
/// <summary>
/// 二维码宽度
/// </summary>
[Required(ErrorMessage = "二维码宽度不能为空")]
public int? QrcodeWidth { get; set; }
/// <summary>
/// 业务参数
/// </summary>
public ExtendParams ExtendParams { get; set; }
/// <summary>
/// 商户业务数据
/// </summary>
public Dictionary<string, object> BusinessParams { get; set; }
/// <summary>
/// 开票信息
/// </summary>
public InvoiceInfo InvoiceInfo { get; set; }
/// <summary>
/// 外部买家信息
/// </summary>
public ExtUserInfo ExtUserInfo { get; set; }
}
public class AlipayPreCreateInput
{
/// <summary>
/// 商户订单号
/// </summary>
[Required(ErrorMessage = "商户订单号不能为空")]
public string OutTradeNo { get; set; }
/// <summary>
/// 订单总金额
/// </summary>
[Required(ErrorMessage = "订单总金额不能为空")]
public string TotalAmount { get; set; }
/// <summary>
/// 订单标题
/// </summary>
[Required(ErrorMessage = "订单标题不能为空")]
public string Subject { get; set; }
/// <summary>
/// 超时时间
/// </summary>
public string TimeoutExpress { get; set; }
}
public class AlipayAuthInfoInput
{
/// <summary>
/// 用户Id
/// </summary>
public string UserId { get; set; }
/// <summary>
/// 授权码
/// </summary>
public string AuthCode { get; set; }
}

View File

@ -0,0 +1,31 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Aop.Api.Response;
namespace Admin.NET.Core.Service.Alipay;
/// <summary>
/// 支付宝回调接口
/// </summary>
public abstract class IAlipayNotify
{
/// <summary>
/// 充值回调方法
/// </summary>
/// <param name="type">交易类型</param>
/// <param name="tradeNo">交易id</param>
public abstract bool TopUpCallback(long type, long tradeNo);
/// <summary>
/// 扫码回调
/// </summary>
/// <param name="type"></param>
/// <param name="userId"></param>
/// <param name="response"></param>
/// <returns></returns>
public abstract bool ScanCallback(long type, long userId, AlipayUserInfoShareResponse response);
}

View File

@ -20,7 +20,7 @@ public class AdminResultProvider : IUnifyResultProvider
/// <returns></returns>
public IActionResult OnAuthorizeException(DefaultHttpContext context, ExceptionMetadata metadata)
{
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, errors: metadata.Errors), UnifyContext.GetSerializerSettings(context));
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, msg: metadata.Errors), UnifyContext.GetSerializerSettings(context));
}
/// <summary>
@ -31,7 +31,7 @@ public class AdminResultProvider : IUnifyResultProvider
/// <returns></returns>
public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
{
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, errors: metadata.Errors), UnifyContext.GetSerializerSettings(context));
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, msg: metadata.Errors), UnifyContext.GetSerializerSettings(context));
}
/// <summary>
@ -53,7 +53,7 @@ public class AdminResultProvider : IUnifyResultProvider
/// <returns></returns>
public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)
{
return new JsonResult(RESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, data: metadata.Data, errors: metadata.ValidationResult), UnifyContext.GetSerializerSettings(context));
return new JsonResult(RESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, data: metadata.Data, msg: metadata.ValidationResult), UnifyContext.GetSerializerSettings(context));
}
/// <summary>
@ -76,12 +76,12 @@ public class AdminResultProvider : IUnifyResultProvider
// 若存在身份验证失败消息,则返回消息内容
if (context.Items.TryGetValue(SignatureAuthenticationDefaults.AuthenticateFailMsgKey, out var authFailMsg))
msg = authFailMsg + "";
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: msg),
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, msg: msg),
App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
break;
// 处理 403 状态码
case StatusCodes.Status403Forbidden:
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 禁止访问,没有权限"),
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, msg: "403 禁止访问,没有权限"),
App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
break;
// 处理 302 状态码
@ -93,7 +93,7 @@ public class AdminResultProvider : IUnifyResultProvider
else
{
var errorMessage = "302 跳转失败,没有提供 Location 头信息";
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: errorMessage),
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, msg: errorMessage),
App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
}
break;
@ -108,9 +108,9 @@ public class AdminResultProvider : IUnifyResultProvider
/// <param name="statusCode"></param>
/// <param name="succeeded"></param>
/// <param name="data"></param>
/// <param name="errors"></param>
/// <param name="msg"></param>
/// <returns></returns>
private static AdminResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)
private static AdminResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object msg = default)
{
//// 统一返回值脱敏处理
//if (data?.GetType() == typeof(String))
@ -125,7 +125,7 @@ public class AdminResultProvider : IUnifyResultProvider
return new AdminResult<object>
{
Code = statusCode,
Message = errors is null or string ? (errors + "") : JSON.Serialize(errors),
Message = msg is null or string ? (msg + "") : JSON.Serialize(msg),
Result = data,
Type = succeeded ? "success" : "error",
Extras = UnifyContext.Take(),

View File

@ -81,6 +81,23 @@ public static class CommonUtil
return result;
}
/// <summary>
/// 获取请求地址源
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public static string GetOrigin(this HttpRequest request)
{
string scheme = request.Scheme;
string host = request.Host.Host;
int port = request.Host.Port ?? (-1);
string url = $"{scheme}://{host}";
if (port != 80 && port != 443 && port != -1) url += $":{port}";
return url;
}
/// <summary>
/// 对象序列化XML
/// </summary>

View File

@ -21,6 +21,7 @@ public class ExcelHelper
try
{
var result = CommonUtil.ImportExcelDataAsync<IN>(file).Result ?? throw Oops.Oh("有效数据为空");
result.ForEach(u => u.Id = YitIdHelper.NextId());
var tasks = new List<Task>();
action.Invoke(result, (storageable, pageItems, rows) =>
@ -28,12 +29,14 @@ public class ExcelHelper
// 标记校验信息
tasks.Add(Task.Run(() =>
{
if (storageable.TotalList.Any())
{
for (int i = 0; i < rows.Count; i++) pageItems[i].Id = rows[i].Id;
if (!storageable.TotalList.Any()) return;
for (int i = 0; i < storageable.TotalList.Count; i++)
pageItems[i].Error ??= storageable.TotalList[i].StorageMessage;
// 通过Id标记校验信息
var itemMap = pageItems.ToDictionary(u => u.Id, u => u);
foreach (var item in storageable.TotalList)
{
var temp = itemMap.GetValueOrDefault(item.Item.Id);
if (temp != null) temp.Error ??= item.StorageMessage;
}
}));
});
@ -41,7 +44,9 @@ public class ExcelHelper
// 等待所有标记验证信息任务完成
Task.WhenAll(tasks).GetAwaiter().GetResult();
return ExportData(result);
// 仅导出错误记录
var errorList = result.Where(u => !string.IsNullOrWhiteSpace(u.Error));
return ExportData(errorList.Any() ? errorList : new List<IN>());
}
catch (Exception ex)
{
@ -59,7 +64,7 @@ public class ExcelHelper
}
/// <summary>
/// 导出xlsx数据
/// 导出Xlsx数据
/// </summary>
/// <param name="list"></param>
/// <param name="fileName"></param>
@ -72,7 +77,7 @@ public class ExcelHelper
}
/// <summary>
/// 根据类型导出xlsx模板
/// 根据类型导出Xlsx模板
/// </summary>
/// <param name="list"></param>
/// <param name="filename"></param>

View File

@ -37,6 +37,7 @@ public static class ProjectOptions
services.AddConfigurableOptions<CryptogramOptions>();
services.AddConfigurableOptions<SMSOptions>();
services.AddConfigurableOptions<EventBusOptions>();
services.AddConfigurableOptions<AlipayOptions>();
services.Configure<IpRateLimitOptions>(App.Configuration.GetSection("IpRateLimiting"));
services.Configure<IpRateLimitPolicies>(App.Configuration.GetSection("IpRateLimitPolicies"));
services.Configure<ClientRateLimitOptions>(App.Configuration.GetSection("ClientRateLimiting"));

View File

@ -12,6 +12,7 @@
* Do not edit the class manually.
*/
export * from './apis/apijsonapi';
export * from './apis/alipay-api';
export * from './apis/sys-app-api';
export * from './apis/sys-auth-api';
export * from './apis/sys-cache-api';

View File

@ -0,0 +1,389 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Configuration } from '../configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
import { AdminResultString } from '../models';
import { AlipayPreCreateInput } from '../models';
import { AlipayTradePagePayInput } from '../models';
/**
* AlipayApi - axios parameter creator
* @export
*/
export const AlipayApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary 🔖
* @param {AlipayPreCreateInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiAlipayAlipayPreCreatePost: async (body?: AlipayPreCreateInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/alipay/alipayPreCreate`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {AlipayTradePagePayInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiAlipayAlipayTradePagePayPost: async (body?: AlipayTradePagePayInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/alipay/alipayTradePagePay`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {string} [userId] Id
* @param {string} [authCode]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiAlipayGetAuthInfoGet: async (userId?: string, authCode?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/alipay/getAuthInfo`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
if (userId !== undefined) {
localVarQueryParameter['UserId'] = userId;
}
if (authCode !== undefined) {
localVarQueryParameter['AuthCode'] = authCode;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiAlipayNotifyPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/alipay/notify`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
}
};
/**
* AlipayApi - functional programming interface
* @export
*/
export const AlipayApiFp = function(configuration?: Configuration) {
return {
/**
*
* @summary 🔖
* @param {AlipayPreCreateInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayAlipayPreCreatePost(body?: AlipayPreCreateInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
const localVarAxiosArgs = await AlipayApiAxiosParamCreator(configuration).apiAlipayAlipayPreCreatePost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {AlipayTradePagePayInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayAlipayTradePagePayPost(body?: AlipayTradePagePayInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
const localVarAxiosArgs = await AlipayApiAxiosParamCreator(configuration).apiAlipayAlipayTradePagePayPost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {string} [userId] Id
* @param {string} [authCode]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayGetAuthInfoGet(userId?: string, authCode?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await AlipayApiAxiosParamCreator(configuration).apiAlipayGetAuthInfoGet(userId, authCode, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayNotifyPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
const localVarAxiosArgs = await AlipayApiAxiosParamCreator(configuration).apiAlipayNotifyPost(options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
}
};
/**
* AlipayApi - factory interface
* @export
*/
export const AlipayApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
return {
/**
*
* @summary 🔖
* @param {AlipayPreCreateInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayAlipayPreCreatePost(body?: AlipayPreCreateInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(configuration).apiAlipayAlipayPreCreatePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {AlipayTradePagePayInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayAlipayTradePagePayPost(body?: AlipayTradePagePayInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(configuration).apiAlipayAlipayTradePagePayPost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {string} [userId] Id
* @param {string} [authCode]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayGetAuthInfoGet(userId?: string, authCode?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return AlipayApiFp(configuration).apiAlipayGetAuthInfoGet(userId, authCode, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiAlipayNotifyPost(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(configuration).apiAlipayNotifyPost(options).then((request) => request(axios, basePath));
},
};
};
/**
* AlipayApi - object-oriented interface
* @export
* @class AlipayApi
* @extends {BaseAPI}
*/
export class AlipayApi extends BaseAPI {
/**
*
* @summary 🔖
* @param {AlipayPreCreateInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AlipayApi
*/
public async apiAlipayAlipayPreCreatePost(body?: AlipayPreCreateInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(this.configuration).apiAlipayAlipayPreCreatePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {AlipayTradePagePayInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AlipayApi
*/
public async apiAlipayAlipayTradePagePayPost(body?: AlipayTradePagePayInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(this.configuration).apiAlipayAlipayTradePagePayPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {string} [userId] Id
* @param {string} [authCode]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AlipayApi
*/
public async apiAlipayGetAuthInfoGet(userId?: string, authCode?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return AlipayApiFp(this.configuration).apiAlipayGetAuthInfoGet(userId, authCode, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AlipayApi
*/
public async apiAlipayNotifyPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
return AlipayApiFp(this.configuration).apiAlipayNotifyPost(options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -0,0 +1,54 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface AlipayPreCreateInput
*/
export interface AlipayPreCreateInput {
/**
*
*
* @type {string}
* @memberof AlipayPreCreateInput
*/
outTradeNo: string;
/**
*
*
* @type {string}
* @memberof AlipayPreCreateInput
*/
totalAmount: string;
/**
*
*
* @type {string}
* @memberof AlipayPreCreateInput
*/
subject: string;
/**
*
*
* @type {string}
* @memberof AlipayPreCreateInput
*/
timeoutExpress?: string | null;
}

View File

@ -0,0 +1,97 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { ExtUserInfo } from './ext-user-info';
import { ExtendParams } from './extend-params';
import { InvoiceInfo } from './invoice-info';
/**
*
*
* @export
* @interface AlipayTradePagePayInput
*/
export interface AlipayTradePagePayInput {
/**
*
*
* @type {string}
* @memberof AlipayTradePagePayInput
*/
outTradeNo: string;
/**
*
*
* @type {string}
* @memberof AlipayTradePagePayInput
*/
totalAmount: string;
/**
*
*
* @type {string}
* @memberof AlipayTradePagePayInput
*/
subject: string;
/**
* @type {string}
* @memberof AlipayTradePagePayInput
*/
body?: string | null;
/**
*
*
* @type {string}
* @memberof AlipayTradePagePayInput
*/
timeoutExpress?: string | null;
/**
*
*
* @type {number}
* @memberof AlipayTradePagePayInput
*/
qrcodeWidth: number;
/**
* @type {ExtendParams}
* @memberof AlipayTradePagePayInput
*/
extendParams?: ExtendParams;
/**
*
*
* @type {{ [key: string]: any; }}
* @memberof AlipayTradePagePayInput
*/
businessParams?: { [key: string]: any; } | null;
/**
* @type {InvoiceInfo}
* @memberof AlipayTradePagePayInput
*/
invoiceInfo?: InvoiceInfo;
/**
* @type {ExtUserInfo}
* @memberof AlipayTradePagePayInput
*/
extUserInfo?: ExtUserInfo;
}

View File

@ -0,0 +1,70 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface ExtUserInfo
*/
export interface ExtUserInfo {
/**
* @type {string}
* @memberof ExtUserInfo
*/
certNo?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
certType?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
fixBuyer?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
identityHash?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
minAge?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
mobile?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
name?: string | null;
/**
* @type {string}
* @memberof ExtUserInfo
*/
needCheckInfo?: string | null;
}

View File

@ -0,0 +1,82 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface ExtendParams
*/
export interface ExtendParams {
/**
* @type {string}
* @memberof ExtendParams
*/
cardType?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
creditExtInfo?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
hbFqNum?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
hbFqSellerPercent?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
industryRefluxInfo?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
royaltyFreeze?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
specifiedSellerName?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
sysServiceProviderId?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
tcInstallmentOrderId?: string | null;
/**
* @type {string}
* @memberof ExtendParams
*/
tradeComponentOrderId?: string | null;
}

View File

@ -128,6 +128,8 @@ export * from './admin-result-visual-db-table';
export * from './admin-result-wechat-pay-output';
export * from './admin-result-wx-open-id-output';
export * from './admin-result-wx-phone-output';
export * from './alipay-pre-create-input';
export * from './alipay-trade-page-pay-input';
export * from './aliyun-send-sms-template-input';
export * from './amount';
export * from './api-output';
@ -212,6 +214,8 @@ export * from './event-attributes';
export * from './event-info';
export * from './export-proc-by-tmpinput';
export * from './export-proc-input';
export * from './ext-user-info';
export * from './extend-params';
export * from './field-attributes';
export * from './field-info';
export * from './filter';
@ -238,6 +242,8 @@ export * from './idisposable';
export * from './isite';
export * from './info-save-input';
export * from './int-ptr';
export * from './invoice-info';
export * from './invoice-key-info';
export * from './jtoken';
export * from './job-create-type-enum';
export * from './job-detail-input';

View File

@ -0,0 +1,35 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { InvoiceKeyInfo } from './invoice-key-info';
/**
*
*
* @export
* @interface InvoiceInfo
*/
export interface InvoiceInfo {
/**
* @type {string}
* @memberof InvoiceInfo
*/
details?: string | null;
/**
* @type {InvoiceKeyInfo}
* @memberof InvoiceInfo
*/
keyInfo?: InvoiceKeyInfo;
}

View File

@ -0,0 +1,40 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface InvoiceKeyInfo
*/
export interface InvoiceKeyInfo {
/**
* @type {string}
* @memberof InvoiceKeyInfo
*/
invoiceMerchantName?: string | null;
/**
* @type {boolean}
* @memberof InvoiceKeyInfo
*/
isSupportInvoice?: boolean;
/**
* @type {string}
* @memberof InvoiceKeyInfo
*/
taxNum?: string | null;
}