231
This commit is contained in:
parent
53a61f6298
commit
11ee8d963c
|
|
@ -57,11 +57,6 @@ try
|
||||||
builder.Configuration.GetSection("JwtSettings").Bind(jwtSettings);
|
builder.Configuration.GetSection("JwtSettings").Bind(jwtSettings);
|
||||||
builder.Services.AddSingleton(jwtSettings);
|
builder.Services.AddSingleton(jwtSettings);
|
||||||
|
|
||||||
// 配置微信设置
|
|
||||||
var wechatSettings = new WechatSettings();
|
|
||||||
builder.Configuration.GetSection("WechatSettings").Bind(wechatSettings);
|
|
||||||
builder.Services.AddSingleton(wechatSettings);
|
|
||||||
|
|
||||||
// 配置高德地图设置
|
// 配置高德地图设置
|
||||||
var amapSettings = new AmapSettings();
|
var amapSettings = new AmapSettings();
|
||||||
builder.Configuration.GetSection("AmapSettings").Bind(amapSettings);
|
builder.Configuration.GetSection("AmapSettings").Bind(amapSettings);
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,6 @@
|
||||||
"DefaultConnection": "Server=192.168.195.15;uid=sa;pwd=Dbt@com@123;Database=honey_box;MultipleActiveResultSets=true;pooling=true;min pool size=5;max pool size=32767;connect timeout=20;Encrypt=True;TrustServerCertificate=True;",
|
"DefaultConnection": "Server=192.168.195.15;uid=sa;pwd=Dbt@com@123;Database=honey_box;MultipleActiveResultSets=true;pooling=true;min pool size=5;max pool size=32767;connect timeout=20;Encrypt=True;TrustServerCertificate=True;",
|
||||||
"Redis": "192.168.195.15:6379,abortConnect=false,connectTimeout=5000"
|
"Redis": "192.168.195.15:6379,abortConnect=false,connectTimeout=5000"
|
||||||
},
|
},
|
||||||
"WechatSettings": {
|
|
||||||
"AppId": "",
|
|
||||||
"AppSecret": ""
|
|
||||||
},
|
|
||||||
"WechatPaySettings": {
|
"WechatPaySettings": {
|
||||||
"DefaultMerchant": {
|
"DefaultMerchant": {
|
||||||
"Name": "默认商户",
|
"Name": "默认商户",
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ public class WechatService : IWechatService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly ILogger<WechatService> _logger;
|
private readonly ILogger<WechatService> _logger;
|
||||||
private readonly WechatSettings _wechatSettings;
|
|
||||||
private readonly WechatPaySettings _wechatPaySettings;
|
private readonly WechatPaySettings _wechatPaySettings;
|
||||||
private readonly IRedisService _redisService;
|
private readonly IRedisService _redisService;
|
||||||
private readonly HoneyBoxDbContext _dbContext;
|
private readonly HoneyBoxDbContext _dbContext;
|
||||||
|
|
@ -33,14 +32,12 @@ public class WechatService : IWechatService
|
||||||
public WechatService(
|
public WechatService(
|
||||||
HttpClient httpClient,
|
HttpClient httpClient,
|
||||||
ILogger<WechatService> logger,
|
ILogger<WechatService> logger,
|
||||||
WechatSettings wechatSettings,
|
|
||||||
IOptions<WechatPaySettings> wechatPaySettings,
|
IOptions<WechatPaySettings> wechatPaySettings,
|
||||||
IRedisService redisService,
|
IRedisService redisService,
|
||||||
HoneyBoxDbContext dbContext)
|
HoneyBoxDbContext dbContext)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
|
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
|
||||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
_wechatSettings = wechatSettings ?? throw new ArgumentNullException(nameof(wechatSettings));
|
|
||||||
_wechatPaySettings = wechatPaySettings?.Value ?? throw new ArgumentNullException(nameof(wechatPaySettings));
|
_wechatPaySettings = wechatPaySettings?.Value ?? throw new ArgumentNullException(nameof(wechatPaySettings));
|
||||||
_redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
|
_redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
|
||||||
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
|
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
|
||||||
|
|
@ -67,8 +64,18 @@ public class WechatService : IWechatService
|
||||||
{
|
{
|
||||||
// 从数据库获取微信配置
|
// 从数据库获取微信配置
|
||||||
var wechatConfig = await GetWechatSettingFromDbAsync();
|
var wechatConfig = await GetWechatSettingFromDbAsync();
|
||||||
var appId = wechatConfig?.AppId ?? _wechatSettings.AppId;
|
if (wechatConfig == null)
|
||||||
var appSecret = wechatConfig?.AppSecret ?? _wechatSettings.AppSecret;
|
{
|
||||||
|
_logger.LogError("[微信登录] 未找到小程序配置,请在后台管理系统中配置 miniprogram_setting");
|
||||||
|
return new WechatAuthResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorMessage = "小程序配置未设置,请联系管理员"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var appId = wechatConfig.AppId;
|
||||||
|
var appSecret = wechatConfig.AppSecret;
|
||||||
|
|
||||||
// 记录配置信息(脱敏)
|
// 记录配置信息(脱敏)
|
||||||
var maskedAppId = appId?.Length > 8
|
var maskedAppId = appId?.Length > 8
|
||||||
|
|
@ -77,8 +84,8 @@ public class WechatService : IWechatService
|
||||||
var maskedSecret = string.IsNullOrEmpty(appSecret)
|
var maskedSecret = string.IsNullOrEmpty(appSecret)
|
||||||
? "未配置"
|
? "未配置"
|
||||||
: $"{appSecret.Substring(0, 4)}****";
|
: $"{appSecret.Substring(0, 4)}****";
|
||||||
_logger.LogInformation("[微信登录] 配置信息: AppId={AppId}, AppSecret={AppSecret}, 来源={Source}",
|
_logger.LogInformation("[微信登录] 配置信息: AppId={AppId}, AppSecret={AppSecret}, 来源=数据库",
|
||||||
maskedAppId, maskedSecret, wechatConfig != null ? "数据库" : "appsettings");
|
maskedAppId, maskedSecret);
|
||||||
|
|
||||||
var url = $"{WechatCodeToSessionUrl}?appid={appId}&secret={appSecret}&js_code={code}&grant_type=authorization_code";
|
var url = $"{WechatCodeToSessionUrl}?appid={appId}&secret={appSecret}&js_code={code}&grant_type=authorization_code";
|
||||||
|
|
||||||
|
|
@ -299,15 +306,23 @@ public class WechatService : IWechatService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取小程序接口调用凭证(access_token)
|
/// 获取小程序接口调用凭证(access_token)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appId">小程序AppId(可选,不传则使用默认配置)</param>
|
/// <param name="appId">小程序AppId(可选,不传则使用数据库默认配置)</param>
|
||||||
/// <returns>access_token,失败返回null</returns>
|
/// <returns>access_token,失败返回null</returns>
|
||||||
public async Task<string?> GetAccessTokenAsync(string? appId = null)
|
public async Task<string?> GetAccessTokenAsync(string? appId = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// 从数据库获取配置
|
||||||
|
var wechatConfig = await GetWechatSettingFromDbAsync();
|
||||||
|
if (wechatConfig == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("无法获取access_token:未找到小程序配置,请在后台管理系统中配置 miniprogram_setting");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 确定使用哪个AppId和AppSecret
|
// 确定使用哪个AppId和AppSecret
|
||||||
var targetAppId = appId ?? _wechatSettings.AppId;
|
var targetAppId = appId ?? wechatConfig.AppId;
|
||||||
var targetAppSecret = GetAppSecretByAppId(targetAppId);
|
var targetAppSecret = await GetAppSecretByAppIdAsync(targetAppId);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(targetAppId) || string.IsNullOrEmpty(targetAppSecret))
|
if (string.IsNullOrEmpty(targetAppId) || string.IsNullOrEmpty(targetAppSecret))
|
||||||
{
|
{
|
||||||
|
|
@ -385,14 +400,15 @@ public class WechatService : IWechatService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据AppId获取对应的AppSecret
|
/// 根据AppId获取对应的AppSecret(异步版本,从数据库读取)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string GetAppSecretByAppId(string appId)
|
private async Task<string> GetAppSecretByAppIdAsync(string appId)
|
||||||
{
|
{
|
||||||
// 首先检查默认配置
|
// 从数据库获取配置
|
||||||
if (_wechatSettings.AppId == appId)
|
var wechatConfig = await GetWechatSettingFromDbAsync();
|
||||||
|
if (wechatConfig != null && wechatConfig.AppId == appId)
|
||||||
{
|
{
|
||||||
return _wechatSettings.AppSecret;
|
return wechatConfig.AppSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从小程序配置列表中查找
|
// 从小程序配置列表中查找
|
||||||
|
|
@ -402,9 +418,9 @@ public class WechatService : IWechatService
|
||||||
return miniprogram.AppSecret;
|
return miniprogram.AppSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果都没找到,返回默认配置的AppSecret
|
// 如果都没找到,返回数据库默认配置的AppSecret
|
||||||
_logger.LogWarning("未找到AppId {AppId} 的配置,使用默认AppSecret", appId);
|
_logger.LogWarning("未找到AppId {AppId} 的配置,使用数据库默认配置", appId);
|
||||||
return _wechatSettings.AppSecret;
|
return wechatConfig?.AppSecret ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -598,24 +614,32 @@ public class WechatService : IWechatService
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从数据库获取微信小程序配置
|
/// 从数据库获取微信小程序配置
|
||||||
/// 优先从 miniprogram_setting 读取默认小程序配置,如果没有则回退到 wechat_setting
|
/// 仅从 miniprogram_setting 读取,无配置则返回 null
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<WechatSettings?> GetWechatSettingFromDbAsync()
|
private async Task<WechatSettings?> GetWechatSettingFromDbAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 1. 优先从 miniprogram_setting 读取默认小程序配置
|
// 从 miniprogram_setting 读取小程序配置
|
||||||
var miniprogramConfig = await _dbContext.Configs
|
var miniprogramConfig = await _dbContext.Configs
|
||||||
.Where(c => c.ConfigKey == "miniprogram_setting")
|
.Where(c => c.ConfigKey == "miniprogram_setting")
|
||||||
.Select(c => c.ConfigValue)
|
.Select(c => c.ConfigValue)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(miniprogramConfig))
|
if (string.IsNullOrEmpty(miniprogramConfig))
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("[微信配置] 数据库中未找到 miniprogram_setting 配置");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var config = JsonSerializer.Deserialize<JsonElement>(miniprogramConfig);
|
var config = JsonSerializer.Deserialize<JsonElement>(miniprogramConfig);
|
||||||
|
|
||||||
if (config.TryGetProperty("miniprograms", out var miniprograms) && miniprograms.ValueKind == JsonValueKind.Array)
|
if (!config.TryGetProperty("miniprograms", out var miniprograms) || miniprograms.ValueKind != JsonValueKind.Array)
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("[微信配置] miniprogram_setting 配置格式错误,缺少 miniprograms 数组");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 查找默认小程序配置 (is_default = 1)
|
// 查找默认小程序配置 (is_default = 1)
|
||||||
foreach (var mp in miniprograms.EnumerateArray())
|
foreach (var mp in miniprograms.EnumerateArray())
|
||||||
{
|
{
|
||||||
|
|
@ -658,86 +682,59 @@ public class WechatService : IWechatService
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 回退到 wechat_setting(旧版单一配置)
|
_logger.LogWarning("[微信配置] miniprogram_setting 中未找到有效的小程序配置");
|
||||||
var wechatSettingConfig = await _dbContext.Configs
|
return null;
|
||||||
.Where(c => c.ConfigKey == "wechat_setting")
|
|
||||||
.Select(c => c.ConfigValue)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(wechatSettingConfig))
|
|
||||||
{
|
|
||||||
var config = JsonSerializer.Deserialize<JsonElement>(wechatSettingConfig);
|
|
||||||
|
|
||||||
var appId = config.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
|
|
||||||
var appSecret = config.TryGetProperty("appSecret", out var appSecretProp) ? appSecretProp.GetString() : null;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(appId) && !string.IsNullOrEmpty(appSecret))
|
|
||||||
{
|
|
||||||
_logger.LogDebug("[微信配置] 从 wechat_setting 读取配置: AppId={AppId}",
|
|
||||||
appId.Length > 8 ? $"{appId.Substring(0, 4)}****{appId.Substring(appId.Length - 4)}" : appId);
|
|
||||||
return new WechatSettings
|
|
||||||
{
|
|
||||||
AppId = appId,
|
|
||||||
AppSecret = appSecret
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogDebug("[微信配置] 数据库中未找到有效的微信配置");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning(ex, "[微信配置] 从数据库读取配置失败");
|
_logger.LogError(ex, "[微信配置] 从数据库读取配置失败");
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取商户配置(优先从数据库读取)
|
/// 获取商户配置(从数据库读取)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<WechatPayMerchantConfig?> GetMerchantConfigAsync()
|
private async Task<WechatPayMerchantConfig?> GetMerchantConfigAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 1. 尝试从数据库读取 weixinpay 配置
|
// 从数据库读取 weixinpay 配置
|
||||||
var weixinpayConfig = await _dbContext.Configs
|
var weixinpayConfig = await _dbContext.Configs
|
||||||
.Where(c => c.ConfigKey == "weixinpay")
|
.Where(c => c.ConfigKey == "weixinpay")
|
||||||
.Select(c => c.ConfigValue)
|
.Select(c => c.ConfigValue)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(weixinpayConfig))
|
if (string.IsNullOrEmpty(weixinpayConfig))
|
||||||
{
|
{
|
||||||
|
_logger.LogError("[微信支付] 数据库中未找到 weixinpay 配置");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var config = JsonSerializer.Deserialize<JsonElement>(weixinpayConfig);
|
var config = JsonSerializer.Deserialize<JsonElement>(weixinpayConfig);
|
||||||
|
|
||||||
var mchId = config.TryGetProperty("mch_id", out var mchIdProp) ? mchIdProp.GetString() : null;
|
var mchId = config.TryGetProperty("mch_id", out var mchIdProp) ? mchIdProp.GetString() : null;
|
||||||
var appId = config.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
|
var appId = config.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
|
||||||
var key = config.TryGetProperty("keys", out var keysProp) ? keysProp.GetString() : null;
|
var key = config.TryGetProperty("keys", out var keysProp) ? keysProp.GetString() : null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(mchId) && !string.IsNullOrEmpty(key))
|
if (string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(key))
|
||||||
{
|
{
|
||||||
// 如果 weixinpay 中没有 appid,尝试从 wechat_setting 获取
|
_logger.LogError("[微信支付] weixinpay 配置不完整,缺少 mch_id 或 keys");
|
||||||
if (string.IsNullOrEmpty(appId))
|
return null;
|
||||||
{
|
|
||||||
var wechatSettingConfig = await _dbContext.Configs
|
|
||||||
.Where(c => c.ConfigKey == "wechat_setting")
|
|
||||||
.Select(c => c.ConfigValue)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(wechatSettingConfig))
|
|
||||||
{
|
|
||||||
var wechatSetting = JsonSerializer.Deserialize<JsonElement>(wechatSettingConfig);
|
|
||||||
appId = wechatSetting.TryGetProperty("appid", out var wechatAppIdProp) ? wechatAppIdProp.GetString() : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果还是没有 appid,使用 appsettings.json 中的配置
|
// 如果 weixinpay 中没有 appid,从 miniprogram_setting 获取
|
||||||
if (string.IsNullOrEmpty(appId))
|
if (string.IsNullOrEmpty(appId))
|
||||||
{
|
{
|
||||||
appId = _wechatSettings.AppId;
|
var wechatConfig = await GetWechatSettingFromDbAsync();
|
||||||
|
appId = wechatConfig?.AppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(appId))
|
||||||
|
{
|
||||||
|
_logger.LogError("[微信支付] 未找到有效的 AppId 配置");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("[微信支付] 从数据库读取配置: MchId={MchId}, AppId={AppId}", mchId, appId);
|
_logger.LogInformation("[微信支付] 从数据库读取配置: MchId={MchId}, AppId={AppId}", mchId, appId);
|
||||||
|
|
@ -745,43 +742,17 @@ public class WechatService : IWechatService
|
||||||
{
|
{
|
||||||
Name = "数据库配置",
|
Name = "数据库配置",
|
||||||
MchId = mchId,
|
MchId = mchId,
|
||||||
AppId = appId ?? string.Empty,
|
AppId = appId,
|
||||||
Key = key,
|
Key = key,
|
||||||
OrderPrefix = "MYH",
|
OrderPrefix = "MYH",
|
||||||
Weight = 1
|
Weight = 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogWarning("[微信支付] 数据库中未找到有效的微信支付配置,使用 appsettings.json 配置");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning(ex, "[微信支付] 从数据库读取配置失败,使用 appsettings.json 配置");
|
_logger.LogError(ex, "[微信支付] 从数据库读取配置失败");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 回退到 appsettings.json 配置
|
|
||||||
if (!string.IsNullOrEmpty(_wechatPaySettings.DefaultMerchant?.MchId))
|
|
||||||
{
|
|
||||||
return _wechatPaySettings.DefaultMerchant;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _wechatPaySettings.Merchants.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取商户配置(同步版本,用于兼容)
|
|
||||||
/// </summary>
|
|
||||||
private WechatPayMerchantConfig? GetMerchantConfig()
|
|
||||||
{
|
|
||||||
// 优先使用 appsettings.json 中的默认商户配置
|
|
||||||
if (!string.IsNullOrEmpty(_wechatPaySettings.DefaultMerchant?.MchId))
|
|
||||||
{
|
|
||||||
return _wechatPaySettings.DefaultMerchant;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从商户列表中获取第一个
|
|
||||||
return _wechatPaySettings.Merchants.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,10 @@ public class ServiceModule : Module
|
||||||
{
|
{
|
||||||
var httpClientFactory = c.Resolve<System.Net.Http.IHttpClientFactory>();
|
var httpClientFactory = c.Resolve<System.Net.Http.IHttpClientFactory>();
|
||||||
var logger = c.Resolve<ILogger<WechatService>>();
|
var logger = c.Resolve<ILogger<WechatService>>();
|
||||||
var wechatSettings = c.Resolve<WechatSettings>();
|
|
||||||
var wechatPaySettings = c.Resolve<Microsoft.Extensions.Options.IOptions<WechatPaySettings>>();
|
var wechatPaySettings = c.Resolve<Microsoft.Extensions.Options.IOptions<WechatPaySettings>>();
|
||||||
var redisService = c.Resolve<IRedisService>();
|
var redisService = c.Resolve<IRedisService>();
|
||||||
var dbContext = c.Resolve<HoneyBoxDbContext>();
|
var dbContext = c.Resolve<HoneyBoxDbContext>();
|
||||||
return new WechatService(httpClientFactory.CreateClient(), logger, wechatSettings, wechatPaySettings, redisService, dbContext);
|
return new WechatService(httpClientFactory.CreateClient(), logger, wechatPaySettings, redisService, dbContext);
|
||||||
}).As<IWechatService>().InstancePerLifetimeScope();
|
}).As<IWechatService>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
// 注册 IP 地理位置服务
|
// 注册 IP 地理位置服务
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user