提交代码

This commit is contained in:
zpc 2024-08-27 01:02:46 +08:00
parent 9140db4e33
commit c8796befe6
9 changed files with 234 additions and 24 deletions

View File

@ -10,13 +10,14 @@ using Alipay.EasySDK.Kernel;
using Alipay.EasySDK.Kernel.Util;
using Alipay.EasySDK.Payment.FaceToFace.Models;
using StackExchange.Redis;
using HuanMeng.DotNetCore.MultiTenant.Contract;
namespace HuanMeng.MiaoYu.Code.Payment.Alipay
{
/// <summary>
///
/// </summary>
public class AlipayPayment : IPayment
public class AlipayPayment(Config config, ITenantInfo tenantInfo) : IPayment
{
public Task<(string orderId, string order)> CreateOrder(string productName, decimal price, params object[] args)
{
@ -31,12 +32,11 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
}
var orderId = GenerateTimestampIdWithOffset();
//.SetOptions(GetConfig());
var response = Factory.Payment.App().Optional("passback_params", "PaymentType%3Dzfb").Pay(productName, orderId, priceStr);
if (ResponseChecker.Success(response))
{
Console.WriteLine("调用成功");
}
else
//AsyncNotify
//https://pay.shhuanmeng.com/api/${tenant}/zfb/${orderId}
var notifyUrl = config.NotifyUrl.Replace("${pay}", "zfb").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier); ;
var response = Factory.Payment.App().AsyncNotify(notifyUrl).Optional("passback_params", "PaymentType%3Dzfb").Pay(productName, orderId, priceStr);
if (!ResponseChecker.Success(response))
{
throw new Exception("创建订单失败!" + response.Body);
}
@ -44,6 +44,10 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
var zfbOrderId = response.Body;
return Task.FromResult((orderId, zfbOrderId));
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private string GenerateTimestampIdWithOffset()
{
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); // 获取Unix时间戳毫秒

View File

@ -56,7 +56,7 @@ namespace HuanMeng.MiaoYu.Code.Payment
return builder;
}
public static Config AlipayConfig { get; set; }
/// <summary>
/// 支付
/// </summary>
@ -80,7 +80,9 @@ namespace HuanMeng.MiaoYu.Code.Payment
//可设置异步通知接收服务地址(可选)
NotifyUrl = x.NotifyUrl,
};
AlipayConfig = config;
Factory.SetOptions(config);
}
else
{
@ -93,14 +95,14 @@ namespace HuanMeng.MiaoYu.Code.Payment
/// </summary>
/// <param name="payment"></param>
/// <returns></returns>
public static IPayment GetPayment(string payment)
public static IPayment GetPayment(string payment, MiaoYuBase miaoYuBase)
{
if (payment == "zfb")
{
return new AlipayPayment();
return new AlipayPayment(AlipayConfig, miaoYuBase.TenantInfo);
}
return new WeChatPayment(wxClient, weChatConfig);
return new WeChatPayment(wxClient, weChatConfig, miaoYuBase.TenantInfo);
}
/// <summary>

View File

@ -3,26 +3,28 @@ using HuanMeng.MiaoYu.Code.Payment.Contract;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using Newtonsoft.Json;
using HuanMeng.DotNetCore.MultiTenant.Contract;
namespace HuanMeng.MiaoYu.Code.Payment.WeChat
{
/// <summary>
/// 微信支付
/// </summary>
public class WeChatPayment(WechatTenpayClient client, WeChatConfig weChatConfig) : IPayment
public class WeChatPayment(WechatTenpayClient client, WeChatConfig weChatConfig, ITenantInfo tenantInfo) : IPayment
{
public async Task<(string orderId, string order)> CreateOrder(string productName, decimal price, params object[] args)
{
var orderId = GenerateTimestampIdWithOffset();
//var client = new WechatTenpayClient(wechatTenpayClientOptions);
/* 以 JSAPI 统一下单接口为例 */
var notifyUrl = weChatConfig.NotifyUrl.Replace("${pay}", "wx").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier);
var request = new CreatePayTransactionAppRequest()
{
OutTradeNumber = orderId,
AppId = weChatConfig.AppId,
Description = productName,
ExpireTime = DateTimeOffset.Now.AddMinutes(20),
NotifyUrl = weChatConfig.NotifyUrl,
NotifyUrl = notifyUrl,
Amount = new CreatePayTransactionJsapiRequest.Types.Amount()
{
Total = (int)(price * 100)

View File

@ -68,7 +68,10 @@ namespace HuanMeng.MiaoYu.Code.SysDictionary.DictionaryNetwork
{
dictionaryUrl = configuration.GetSection("SystemConfig:DictionaryUrl").Get<string>() ?? "";
}
if (string.IsNullOrEmpty(dictionaryUrl))
{
return;
}
using var client = httpClientFactory.CreateClient();
var request = await client.GetAsync(dictionaryUrl);
if (request.IsSuccessStatusCode)

View File

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace HuanMeng.MiaoYu.WebPayApi.Controllers
{
[Route("api/[controller]/")]
[ApiController]
public class PayController : ControllerBase
{
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet("{tenant?}/{pay?}/{orderId?}")]
public string Get(string? tenant, string? pay, string? orderId)
{
return "ok";
}
/// <summary>
/// ${tenant}/zfb/${orderId}
/// </summary>
/// <returns></returns>
[HttpPost("{tenant?}/{pay?}/{orderId?}")]
public string Post(string? tenant, string? pay,string? orderId)
{
return $"ok;{pay},{orderId}";
}
}
}

View File

@ -13,7 +13,15 @@
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\0-core\HuanMeng.DotNetCore\HuanMeng.DotNetCore.csproj" />
<ProjectReference Include="..\..\0-core\HuanMeng.MiaoYu.Code\HuanMeng.MiaoYu.Code.csproj" />
<ProjectReference Include="..\..\0-core\HuanMeng.MiaoYu.Model\HuanMeng.MiaoYu.Model.csproj" />
</ItemGroup>
</Project>

View File

@ -1,23 +1,126 @@
using AgileConfig.Client;
using HuanMeng.DotNetCore.CustomExtension;
using HuanMeng.DotNetCore.MiddlewareExtend;
using HuanMeng.DotNetCore.Utility.AssemblyHelper;
using HuanMeng.MiaoYu.Code.Base;
using HuanMeng.MiaoYu.Code.JwtUtil;
using HuanMeng.MiaoYu.Code.MultiTenantUtil;
using HuanMeng.MiaoYu.Code.Other;
using HuanMeng.MiaoYu.Code.Payment;
using HuanMeng.MiaoYu.Code.SysDictionary;
using HuanMeng.MiaoYu.Code.TencentUtile;
using HuanMeng.MiaoYu.Code.Users.UserAccount.VerificationCodeManager;
using HuanMeng.MiaoYu.Model.Dto;
using HuanMeng.MiaoYu.Code.AppExtend;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Serialization;
using Serilog;
using System.Diagnostics;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Host.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext());
builder.AddAppConfigClient();
builder.Services.AddSingleton(typeof(ILogger<MiaoYuBase>), serviceProvider =>
{
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
return loggerFactory.CreateLogger<MiaoYuBase>();
});
// 检索程序集信息
AssemblyInfo assemblyInfo = AssemblyInfoHelper.GetAssemblyInfo();
// Add services to the container.
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor(); //添加httpContext注入访问
#region
var _myAllowSpecificOrigins = "_myAllowSpecificOrigins";
builder.Services.AddCustomCors(_myAllowSpecificOrigins);
#endregion
#region automap
var mapperDomain = AppDomain.CurrentDomain.GetAssemblies().Where(it => it.FullName.Contains("HuanMeng") || it.FullName.Contains("XLib.")).ToList();
Type type = typeof(ResponseUserInfo);
if (type != null)
{
Assembly assembly = Assembly.GetAssembly(type);
if (!mapperDomain.Any(it => it.FullName == assembly.FullName))
{
mapperDomain.Add(assembly);
}
}
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();
builder.Services.AddAutoMapper(mapperDomain);
#endregion
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.AddDictionaryInfo();
//配置路由选项使URL全部小写
//builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.AddPayment();
//添加多租户
builder.AddMultiTenantMiaoYu();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
//if (app.Environment.IsDevelopment())
//{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
app.UseSwagger();
app.UseSwaggerUI();
}
c.EnableDeepLinking();
c.DefaultModelsExpandDepth(3);
c.DefaultModelExpandDepth(3);
c.EnableFilter("true");
//c.RoutePrefix = string.Empty;
c.SwaggerEndpoint("/swagger/v1/swagger.json", "寰梦支付API V1");
});
//}
app.UseSerilogRequestLogging();
app.UseAuthorization();
//自定义初始化
//使用跨域
app.UseCors(_myAllowSpecificOrigins);
app.MapControllers();
app.UseStaticFiles();//静态文件访问配置
//执行扩展中间件
app.UseExceptionMiddleware()
.UseExecutionTimeMiddleware();
#region
app.MapGet("/", () => "请求成功").WithName("默认请求");
var startDateTime = DateTime.Now;
var InformationalVersion = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
Console.WriteLine($"version:{InformationalVersion}");
app.MapGet("/system", () =>
{
using Process currentProcess = Process.GetCurrentProcess();
// CPU使用率 (一般是一个0-100之间的值但实际是时间占比需要转换)
double cpuUsage = currentProcess.TotalProcessorTime.TotalMilliseconds / Environment.TickCount * 100;
// 已用内存 (字节)
long memoryUsage = currentProcess.WorkingSet64;
return new
{
msg = $"系统信息:{assemblyInfo.InformationalVersion},启动时间:{startDateTime.ToString("yyyy-MM-dd HH:mm:ss")},已安全运行时间:{DateTime.Now.Subtract(startDateTime).TotalMinutes.ToString("0.##")}分钟",
assemblyInfo,
startDateTime,
MemoryUsage = $"{memoryUsage / (1024.0 * 1024.0):F2}MB",
CPUUsage = $"{cpuUsage:F2}%"
};
}).WithName("获取系统数据");
#endregion
app.Run();

View File

@ -4,5 +4,12 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AgileConfig": {
"appId": "huanmeng",
"secret": "dfa47997-fb5c-b644-3770-880f5e7fb403",
"nodes": "http://124.220.55.158:94", //使
"env": "DEV",
"name": "PayClient"
}
}

View File

@ -5,5 +5,56 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "../output/logs/info/log-.txt",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Information", //
"shared": true
//"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "../output/logs/error/log-.txt",
"rollingInterval": "Day", //
"restrictedToMinimumLevel": "Error", // // VerboseDebugInformationWarningError Fatal
"shared": true //
// "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "../output/logs/debug/log-.txt",
"rollingInterval": "Day", //
"restrictedToMinimumLevel": "Debug", // // VerboseDebugInformationWarningError Fatal
"shared": true //
// "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
},
"AgileConfig": {
"appId": "huanmeng",
"secret": "dfa47997-fb5c-b644-3770-880f5e7fb403",
"nodes": "http://10.0.12.5:94", //使
"env": "PROD",
"name": "PayClient"
}
}