增加分布式app配置

This commit is contained in:
zpc 2024-08-23 00:30:58 +08:00
parent c9f8d868e8
commit b8dbbc2c61
20 changed files with 569 additions and 220 deletions

View File

@ -5,7 +5,7 @@
# 在解决方案下运行
docker build -t miaoyu:dev-0.0.3 -f src/2-api/HuanMeng.MiaoYu.WebApi/Dockerfile .
docker build -t miaoyu:dev-0.0.4 --build-arg VERSION=7.0 --build-arg TARGET=dev -f src/2-api/HuanMeng.MiaoYu.WebApi/Dockerfile .
docker build -t miaoyuapi:dev-1.2.8 -t miaoyuapi:latest -t 123.207.203.228:92/miaoyuapi:dev-1.2.8 -t 123.207.203.228:92/miaoyuapi:latest --build-arg VERSION=1.2.8 --build-arg TARGET=dev -f src/2-api/HuanMeng.MiaoYu.WebApi/Dockerfile .
docker build -t miaoyuapi:dev-1.3.1 -t miaoyuapi:latest -t 123.207.203.228:92/miaoyuapi:dev-1.3.1 -t 123.207.203.228:92/miaoyuapi:latest --build-arg VERSION=1.2.8 --build-arg TARGET=dev -f src/2-api/HuanMeng.MiaoYu.WebApi/Dockerfile .
docker push 123.207.203.228:92/miaoyuapi:dev-1.2.8
docker push 123.207.203.228:92/miaoyuapi:latest
docker tag miaoyuapi:dev-1.2.7 123.207.203.228:92/miaoyuapi:dev-1.2.7

View File

@ -18,6 +18,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="StackExchange.Redis" Version="2.8.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,44 @@
using HuanMeng.DotNetCore.MultiTenant;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.MiaoYu.Code.AppExtend
{
/// <summary>
/// 项目配置
/// </summary>
public class AppConfig
{
/// <summary>
/// 数据库连接字符串
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// 域名
/// </summary>
public string DomainName { get; set; }
/// <summary>
/// 标识
/// </summary>
public string Identifier { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// redis连接字符串
/// </summary>
public string RedisConnectionString { get; set; }
/// <summary>
/// 租户
/// </summary>
public Guid TenantId { get; set; }
}
}

View File

@ -0,0 +1,178 @@
using AgileConfig.Client;
using HuanMeng.DotNetCore.MultiTenant.Contract;
using HuanMeng.DotNetCore.MultiTenant;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XLib.DotNetCore.CacheHelper;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Protocols;
namespace HuanMeng.MiaoYu.Code.AppExtend
{
/// <summary>
/// app配置项扩展
/// </summary>
public static class AppConfigurationExtend
{
/// <summary>
/// 配置数据
/// </summary>
//public static ConfigClient AppConfigClient { get; set; }
/// <summary>
///
/// </summary>
public static ConfigurationManager ConfigurationManager { get; set; }
/// <summary>
///
/// </summary>
public static ConcurrentDictionary<string, AppConfig> AppConfigs { get; set; } = new ConcurrentDictionary<string, AppConfig>();
/// <summary>
/// 获取配置项
/// </summary>
/// <param name="domainName"></param>
/// <returns></returns>
public static AppConfig GetAppConfig(string domainName)
{
if (AppConfigs.TryGetValue(domainName, out var appConfig))
{
return appConfig;
}
if (AppConfigs.TryGetValue("default", out appConfig))
{
return appConfig;
}
return AppConfigs.FirstOrDefault().Value;
}
/// <summary>
/// 配置版本号
/// </summary>
public static string AppVersion
{
get;
set;
}
/// <summary>
///
/// </summary>
/// <param name="args"></param>
public static void ConfigClient_ConfigChanged(ConfigReloadedArgs args)
{
if (args.OldConfigs.TryGetValue("Version", out var vresion) && args.NewConfigs.TryGetValue("Version", out var newVersion))
{
if (vresion != newVersion)
{
MemoryCacheHelper.cache.Clear();
}
}
VerifyTenant(args);
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static WebApplicationBuilder AddAppConfigClient(this WebApplicationBuilder builder)
{
var configClient = new ConfigClient(builder.Configuration);
builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
//AppConfigClient = configClient;
ConfigurationManager = builder.Configuration;
AppConfigInit(builder.Configuration);
builder.Services.AddScoped<AppConfig>();
return builder;
}
#region
public static ITenantInfo ToITenantInfo(this AppConfig appConfig, ITenantInfo? tenantInfo = null)
{
if (tenantInfo == null)
{
tenantInfo = new TenantInfo();
}
tenantInfo.TenantId = appConfig.TenantId;
tenantInfo.Identifier = appConfig.Identifier;
tenantInfo.Name = appConfig.Name;
tenantInfo.ConnectionString = appConfig.ConnectionString;
return tenantInfo;
}
/// <summary>
/// 验证多租户
/// </summary>
/// <param name="args"></param>
private static void VerifyTenant(ConfigReloadedArgs args)
{
var newTenant = args.NewConfigs.Where(it => it.Key.Contains("Tenant")).ToDictionary();
var oldTenant = args.OldConfigs.Where(it => it.Key.Contains("Tenant")).ToDictionary();
bool areEqual = newTenant.Count == oldTenant.Count &&
!newTenant.Except(oldTenant).Any();
if (!areEqual)
{
//更新缓存
AppConfigInit(ConfigurationManager);
}
}
/// <summary>
/// 初始化租户数据
/// </summary>
/// <param name="configurationManager"></param>
private static void AppConfigInit(ConfigurationManager configurationManager)
{
var tenants = configurationManager.GetSection("Tenant").Get<List<AppConfig>>();
if (tenants != null)
{
ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>();
if (tenants.Count > 0)
{
tenants?.ForEach(t =>
{
if (!_AppConfigs.TryAdd(t.DomainName, t))
{
Console.WriteLine($"{t.DomainName}配置加载失败");
}
if (t.Name == "default")
{
_AppConfigs.TryAdd("default", t);
}
});
if (!_AppConfigs.TryGetValue("default", out var x))
{
_AppConfigs.TryAdd("default", tenants[0]);
}
}
else
{
_AppConfigs.TryAdd("default", new AppConfig());
}
AppConfigs = _AppConfigs;
}
}
#endregion
}
}

View File

@ -0,0 +1,40 @@
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IDatabase = StackExchange.Redis.IDatabase;
namespace HuanMeng.MiaoYu.Code.Base
{
/// <summary>
/// 数据库连接字符串
/// </summary>
public static class RedisConnection
{
/// <summary>
/// 数据库连接
/// </summary>
public static ConcurrentDictionary<string, IDatabase> Redis { get; set; } = new ConcurrentDictionary<string, IDatabase>();
/// <summary>
///
/// </summary>
/// <param name="redisConnection"></param>
/// <returns></returns>
public static IDatabase GetRedis(string redisConnection)
{
if (!Redis.TryGetValue(redisConnection, out var database))
{
var redis = ConnectionMultiplexer.Connect(redisConnection);
database = redis.GetDatabase();
Redis.TryAdd(redisConnection, database);
}
//database.
//database.StringSet("", "", TimeSpan.FromSeconds(10),when: When.NotExists);
return database;
}
}
}

View File

@ -32,18 +32,12 @@ namespace HuanMeng.MiaoYu.Code.MultiTenantUtil
//初始学生数据库
string MiaoYu_SqlServer_Db = builder.Configuration.GetConnectionString("MiaoYu_SqlServer_Db") ?? "";
//添加配置项
//string SunnySports_SqlServer_Db_SunnySport_Admin = builder.Configuration.GetConnectionString("MiaoYu_SqlServer_Db_Admin") ?? "";
MiaoYuMultiTenantConfig miaoYuMultiTenantConfig = new MiaoYuMultiTenantConfig(MiaoYu_SqlServer_Db); builder.Services.AddSingleton<MiaoYuMultiTenantConfig>(miaoYuMultiTenantConfig);
//添加注入全部的多租户配置项
//builder.Services.AddSingleton<MiaoYuMultiTenantConfig>(sunnySportsMultiTenantConfig);
////添加单个租户的配置项
//添加单个租户的配置项
builder.Services.AddScoped<ITenantInfo,TenantInfo>();
////添加教师端用户
//builder.Services.AddScoped<LoginUserModel>();
//builder.Services.AddScoped<TenantInfo>();
//添加DB
//var iDbLog = LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
//添加系统数据库
builder.Services.AddDbContext<MiaoYuContext>((serviceProvider, options) =>
{

View File

@ -1,5 +1,6 @@
using HuanMeng.DotNetCore.MultiTenant;
using HuanMeng.DotNetCore.MultiTenant.Contract;
using HuanMeng.MiaoYu.Code.AppExtend;
using Microsoft.AspNetCore.Http;
@ -36,6 +37,7 @@ namespace HuanMeng.MiaoYu.Code.MultiTenantUtil
public virtual async Task Invoke(HttpContext context,
IServiceProvider _serviceProvider,
ITenantInfo tenantInfo,
AppConfig appConfig,
MiaoYuMultiTenantConfig miaoYuMultiTenantConfig
)
{
@ -43,11 +45,14 @@ namespace HuanMeng.MiaoYu.Code.MultiTenantUtil
{
tenantInfo = new TenantInfo();
}
var _ten = miaoYuMultiTenantConfig.GetMultiTenantCfgDefault();
tenantInfo.ConnectionString = _ten.ConnectionString;
tenantInfo.Identifier = _ten.Identifier;
tenantInfo.TenantId = _ten.TenantId;
tenantInfo.Name = _ten.Name;
var host = context.Request.Host.Host;
var app = AppConfigurationExtend.GetAppConfig(host);
app.ToITenantInfo(tenantInfo);
//var _ten = miaoYuMultiTenantConfig.GetMultiTenantCfgDefault();
//tenantInfo.ConnectionString = _ten.ConnectionString;
//tenantInfo.Identifier = _ten.Identifier;
//tenantInfo.TenantId = _ten.TenantId;
//tenantInfo.Name = _ten.Name;
await _next.Invoke(context);
}
}

View File

@ -0,0 +1,56 @@
using HuanMeng.MiaoYu.Code.Cache.Special;
using HuanMeng.MiaoYu.Code.Payment;
using HuanMeng.MiaoYu.Model.Dto.Order;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.MiaoYu.Code.Order
{
/// <summary>
/// 订单数据
/// </summary>
public class OrderBLL : MiaoYuBase
{
public OrderBLL(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
public async Task<BaseResponse<IntentOrderDto>> CreateOrder(string paymentMethod, string productId)
{
if (_UserId == 0)
{
throw new ArgumentNullException("未登录");
}
if (string.IsNullOrEmpty(productId))
{
throw new ArgumentNullException("产品不能为空");
}
ProductEntityCache productEntityCache = new ProductEntityCache(this);
var products = productEntityCache.GetDataList();
var product = products.FirstOrDefault(it => it.ProductId == productId);
if (product == null)
{
throw new NullReferenceException("未找到所属产品");
}
//productEntityCache.get
//创建订单
var payment = PaymentExtend.GetPayment(paymentMethod);
(var orderId, var order) = payment.CreateOrder(product.ProductName, product.Price.ToString(), product);
var t = product.ToIntentOrder(paymentMethod, orderId);
t.UserId = _UserId;
Dao.daoDbMiaoYu.context.Add(t);
await Dao.daoDbMiaoYu.context.SaveChangesAsync();
var x = new IntentOrderDto()
{
OrderId = orderId,
Payment = order
};
return new BaseResponse<IntentOrderDto>(ResonseCode.Success, "", x);
}
}
}

View File

@ -1,75 +0,0 @@
using AgileConfig.Client;
using Alipay.EasySDK.Kernel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XLib.DotNetCore.CacheHelper;
namespace HuanMeng.MiaoYu.Code.Other
{
/// <summary>
/// app配置项扩展
/// </summary>
public static class AppConfigurationExtend
{
/// <summary>
/// 配置数据
/// </summary>
public static ConfigClient AppConfigClient { get; set; }
/// <summary>
/// 配置版本号
/// </summary>
public static string AppVersion
{
get;
set;
}
/// <summary>
///
/// </summary>
/// <param name="args"></param>
public static void ConfigClient_ConfigChanged(ConfigReloadedArgs args)
{
if (args.OldConfigs.TryGetValue("Version", out var vresion) && args.NewConfigs.TryGetValue("Version", out var newVersion))
{
if (vresion != newVersion)
{
MemoryCacheHelper.cache.Clear();
}
}
}
public static WebApplicationBuilder AddAppConfigClient(this WebApplicationBuilder builder)
{
var configClient = new ConfigClient(builder.Configuration);
builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
//var config = builder.Configuration;
//builder.Host.ConfigureAppConfiguration((context, config) =>
// {
// //new一个client实例无参构造会从本地appsettings.json文件读取配置
// var configClient = new ConfigClient(context.Configuration);
// //使用AddAgileConfig配置一个新的IConfigurationSource
// config.AddAgileConfig(configClient);
// AppConfigClient = configClient;
// ConfigClient_ConfigChanged(null);
// //注册配置项修改事件
// configClient.ConfigChanged += ConfigClient_ConfigChanged;
// });
return builder;
}
}
}

View File

@ -9,6 +9,7 @@ using Alipay.EasySDK.Factory;
using Alipay.EasySDK.Kernel;
using Alipay.EasySDK.Kernel.Util;
using Alipay.EasySDK.Payment.FaceToFace.Models;
using StackExchange.Redis;
namespace HuanMeng.MiaoYu.Code.Payment.Alipay
{
@ -17,7 +18,7 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
/// </summary>
public class AlipayPayment : IPayment
{
public string CreateOrder(string orderId, string productName, string price, params object[] args)
public (string orderId, string order) CreateOrder(string productName, string price, params object[] args)
{
if (string.IsNullOrEmpty(productName))
{
@ -27,10 +28,7 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
{
throw new ArgumentNullException($"价格不能为空!");
}
if (string.IsNullOrEmpty(orderId))
{
orderId = Guid.NewGuid().ToString();
}
var orderId = GenerateTimestampIdWithOffset();
//.SetOptions(GetConfig());
var response = Factory.Payment.App().Pay(productName, orderId, price);
if (ResponseChecker.Success(response))
@ -43,7 +41,13 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
}
//.PreCreate("Apple iPhone11 128G", "2234567234890", "5799.00");
var zfbOrderId = response.Body;
return zfbOrderId;
return (orderId, zfbOrderId);
}
private string GenerateTimestampIdWithOffset()
{
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); // 获取Unix时间戳毫秒
var random = new Random().Next(1000, 9999); // 生成四位随机数
return $"ZFB{timestamp}J001S{random}";
}
}
}

View File

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.MiaoYu.Code.Payment
{
public class AlipayPayment
{
}
}

View File

@ -19,6 +19,6 @@ namespace HuanMeng.MiaoYu.Code.Payment.Contract
/// <param name="price">价格</param>
/// <param name="args">其它参数</param>
/// <returns></returns>
string CreateOrder(string orderId, string productName, string price, params object[] args);
(string orderId,string order) CreateOrder(string productName, string price, params object[] args);
}
}

View File

@ -1,7 +1,13 @@
using Alipay.EasySDK.Factory;
using Alipay.EasySDK.Kernel;
using HuanMeng.MiaoYu.Code.Payment.Alipay;
using HuanMeng.MiaoYu.Code.Payment.Contract;
using HuanMeng.MiaoYu.Model.Dto.Cache;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
@ -16,28 +22,86 @@ namespace HuanMeng.MiaoYu.Code.Payment
/// </summary>
public static class PaymentExtend
{
/// <summary>
/// 支付
/// </su0mmary>
/// <param name="builder"></param>
/// <returns></returns>
public static IHostApplicationBuilder AddAlipay(this IHostApplicationBuilder builder)
{
AddAlipay(builder.Configuration);
return builder;
}
/// <summary>
/// 支付
/// </summary>
/// <param name="configuration"></param>
public static void AddAlipay(IConfiguration configuration)
{
var x = configuration.GetSection("Payment:AlipayConfig").Get<Config>();
var config = new Config()
if (x != null)
{
Protocol = "https",
GatewayHost = "openapi.alipay.com",
SignType = "RSA2",
AppId = "<-- 请填写您的AppId例如2019091767145019 -->",
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
MerchantPrivateKey = "<-- 请填写您的应用私钥例如MIIEvQIBADANB ... ... -->",
//MerchantCertPath = "<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->",
//AlipayCertPath = "<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->",
//AlipayRootCertPath = "<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt -->",
var config = new Config()
{
Protocol = "https",
GatewayHost = "openapi.alipay.com",
SignType = "RSA2",
AppId = x.AppId,
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
MerchantPrivateKey = x.MerchantPrivateKey,
//MerchantCertPath = "<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->",
//AlipayCertPath = "<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->",
//AlipayRootCertPath = "<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt -->",
// 如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
AlipayPublicKey = x.AlipayPublicKey,
//可设置异步通知接收服务地址(可选)
NotifyUrl = x.NotifyUrl,
};
Factory.SetOptions(config);
}
else
{
Console.WriteLine("接入支付失败");
}
}
// 如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
AlipayPublicKey = "<-- 请填写您的支付宝公钥例如MIIBIjANBg... -->",
/// <summary>
///获取支付方式
/// </summary>
/// <param name="payment"></param>
/// <returns></returns>
public static IPayment GetPayment(string payment)
{
if (payment == "zfb")
{
return new AlipayPayment();
}
return new AlipayPayment();
}
//可设置异步通知接收服务地址(可选)
NotifyUrl = "<-- 请填写您的支付类接口异步通知接收服务地址例如https://www.test.com/callback -->",
/// <summary>
///
/// </summary>
/// <param name="productCache"></param>
/// <param name="payment"></param>
/// <param name="orderId"></param>
/// <returns></returns>
public static T_User_IntentOrder ToIntentOrder(this ProductCache productCache, string payment, string orderId)
{
T_User_IntentOrder t_User_IntentOrder = new T_User_IntentOrder()
{
Price = productCache.Price,
CreatedAt = DateTime.Now,
IntentDate = DateTime.Now,
Method = payment,
Notes = "",
ProductId = productCache.ProductId,
Quantity = 1,
Status = 0,
UpdatedAt = DateTime.Now,
OrderId = orderId,
};
Factory.SetOptions(config);
return t_User_IntentOrder;
}
}
}

View File

@ -103,11 +103,6 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
/// </summary>
public virtual DbSet<T_Model_Config> T_Model_Config { get; set; }
/// <summary>
/// 订单表
/// </summary>
public virtual DbSet<T_Orders> T_Orders { get; set; }
/// <summary>
/// 商城表
/// </summary>
@ -148,6 +143,11 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
/// </summary>
public virtual DbSet<T_User_Data> T_User_Data { get; set; }
/// <summary>
/// 意向订单表
/// </summary>
public virtual DbSet<T_User_IntentOrder> T_User_IntentOrder { get; set; }
/// <summary>
/// 用户记忆卡
/// </summary>
@ -580,37 +580,6 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
}
});
modelBuilder.Entity<T_Orders>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_Orders__3214EC070849C94C");
entity.ToTable(tb => tb.HasComment("订单表"));
entity.Property(e => e.Id)
.ValueGeneratedNever()
.HasComment("订单id");
entity.Property(e => e.Amount).HasComment("金币购买数量/道具兑换数量");
entity.Property(e => e.CreateTime)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.OrderType).HasComment("0金币购买1道具兑换");
entity.Property(e => e.PaymentMethod).HasComment("金币购买时的支付方式0wx 1支付宝");
entity.Property(e => e.Price)
.HasComment("花费的钱/花费的金币")
.HasColumnType("money");
entity.Property(e => e.Status).HasComment("0支付中1已支付2已取消");
entity.Property(e => e.TenantId).HasComment("租户id");
entity.Property(e => e.UpdateTime)
.HasComment("更新时间")
.HasColumnType("datetime");
entity.Property(e => e.UserId).HasComment("用户id");
//添加全局筛选器
if (this.TenantInfo != null)
{
entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId);
}
});
modelBuilder.Entity<T_Products>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_Products__3214EC07DC10A165");
@ -873,6 +842,48 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
}
});
modelBuilder.Entity<T_User_IntentOrder>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_User_I__3214EC07D27A8CE9");
entity.ToTable(tb => tb.HasComment("意向订单表"));
entity.Property(e => e.Id).HasComment("主键");
entity.Property(e => e.CreatedAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.IntentDate)
.HasComment("订单创建时间")
.HasColumnType("datetime");
entity.Property(e => e.Method)
.HasMaxLength(1)
.HasComment("支付方式");
entity.Property(e => e.Notes)
.HasMaxLength(200)
.HasComment("备注");
entity.Property(e => e.OrderId)
.HasMaxLength(64)
.HasComment("订单Id");
entity.Property(e => e.Price)
.HasComment("价格")
.HasColumnType("money");
entity.Property(e => e.ProductId)
.HasMaxLength(50)
.HasComment("产品id");
entity.Property(e => e.Quantity).HasComment("数量");
entity.Property(e => e.Status).HasComment("状态");
entity.Property(e => e.TenantId).HasComment("租户");
entity.Property(e => e.UpdatedAt)
.HasComment("修改时间")
.HasColumnType("datetime");
entity.Property(e => e.UserId).HasComment("用户Id");
//添加全局筛选器
if (this.TenantInfo != null)
{
entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId);
}
});
modelBuilder.Entity<T_User_MemoryCard>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_User_M__3214EC0706BA6604");

View File

@ -1,56 +0,0 @@
using System;
namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
/// <summary>
/// 订单表
/// </summary>
public partial class T_Orders: MultiTenantEntity
{
/// <summary>
/// 订单id
/// </summary>
public virtual int Id { get; set; }
public override Guid TenantId { get; set; }
/// <summary>
/// 用户id
/// </summary>
public virtual int UserId { get; set; }
/// <summary>
/// 0金币购买1道具兑换
/// </summary>
public virtual int OrderType { get; set; }
/// <summary>
/// 金币购买数量/道具兑换数量
/// </summary>
public virtual int Amount { get; set; }
/// <summary>
/// 花费的钱/花费的金币
/// </summary>
public virtual decimal Price { get; set; }
/// <summary>
/// 0支付中1已支付2已取消
/// </summary>
public virtual int Status { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public virtual DateTime UpdateTime { get; set; }
/// <summary>
/// 金币购买时的支付方式0wx 1支付宝
/// </summary>
public virtual int? PaymentMethod { get; set; }
}

View File

@ -10,7 +10,7 @@ public partial class T_User_Currency: MultiTenantEntity
public virtual int Id { get; set; }
/// <summary>
/// 货币类型 语珠、免费币
/// 货币类型 付费币、免费币
/// </summary>
public virtual int CurrencyType { get; set; }

View File

@ -0,0 +1,71 @@
using System;
namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
/// <summary>
/// 意向订单表
/// </summary>
public partial class T_User_IntentOrder: MultiTenantEntity
{
/// <summary>
/// 主键
/// </summary>
public virtual int Id { get; set; }
/// <summary>
/// 用户Id
/// </summary>
public virtual int UserId { get; set; }
/// <summary>
/// 产品id
/// </summary>
public virtual string ProductId { get; set; } = null!;
/// <summary>
/// 支付方式
/// </summary>
public virtual string Method { get; set; } = null!;
/// <summary>
/// 价格
/// </summary>
public virtual decimal Price { get; set; }
/// <summary>
/// 数量
/// </summary>
public virtual int Quantity { get; set; }
/// <summary>
/// 状态
/// </summary>
public virtual int Status { get; set; }
/// <summary>
/// 备注
/// </summary>
public virtual string? Notes { get; set; }
/// <summary>
/// 订单创建时间
/// </summary>
public virtual DateTime IntentDate { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime UpdatedAt { get; set; }
public override Guid TenantId { get; set; }
/// <summary>
/// 订单Id
/// </summary>
public virtual string OrderId { get; set; } = null!;
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.MiaoYu.Model.Dto.Order
{
/// <summary>
///
/// </summary>
public class IntentOrderDto
{
/// <summary>
/// 订单编号
/// </summary>
public string OrderId { get; set; }
/// <summary>
/// 支付信息
/// </summary>
public object Payment { get; set; }
}
}

View File

@ -13,7 +13,7 @@ using HuanMeng.MiaoYu.Code.TencentUtile;
using HuanMeng.MiaoYu.Code.Users.UserAccount.VerificationCodeManager;
using HuanMeng.MiaoYu.Model.Dto;
using HuanMeng.MiaoYu.WebApi.Base;
using HuanMeng.MiaoYu.Code.AppExtend;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;
@ -54,7 +54,6 @@ builder.Services.AddSingleton(typeof(ILogger<MiaoYuBase>), serviceProvider =>
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
return loggerFactory.CreateLogger<MiaoYuBase>();
});
//PaymentExtend.AddAlipay(builder.Configuration);
// 检索程序集信息
AssemblyInfo assemblyInfo = AssemblyInfoHelper.GetAssemblyInfo();
// Add services to the container.
@ -141,6 +140,7 @@ builder.Services.AddSwaggerGen(c =>
});
//配置路由选项使URL全部小写
//builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.AddAlipay();
//添加多租户
builder.AddMultiTenantMiaoYu();
//添加腾讯云管理

View File

@ -84,6 +84,7 @@
},
"SystemConfig": {
"DictionaryUrl": "https://adminapi.shhuanmeng.com/api/v1/admin/SysDictionary/GetList",
"TextCensorDir": "DataStorage/TextCensor/"
},
"AgileConfig": {