itfx/src/InterfaceForward.Repositories/InterfaceForwardQuery.cs
2024-12-06 15:30:41 +08:00

353 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Fake;
using InterfaceForward.Domain.Shared.Dtos;
using InterfaceForward.Domain.Shared.Enum;
using InterfaceForward.Domain.Shared.Helpers;
using InterfaceForward.Repositories.App.Entitys;
using InterfaceForward.Repositories.App.ValueObjects;
using InterfaceForward.Repositories.Dictionary.Entitys;
using InterfaceForward.Repositories.Interface.Entitys;
using InterfaceForward.Repositories.Parameter.Entities;
using InterfaceForward.Repositories.ServiceProvider.Entitys;
namespace InterfaceForward.Repositories;
/// <summary>
///
/// </summary>
public class InterfaceForwardQuery : BasicRepository<FixedParameterEntity>, IScopedDependency
{
/// <summary>
/// 通过服务商id和主体id查找账户id如果账户不存在则返回null
/// </summary>
/// <param name="serviceProviderId">服务商id</param>
/// <param name="appId">应用id</param>
/// <returns></returns>
public async Task<int> GetAccountIdAsync(int serviceProviderId, int appId)
{
return await Context.Queryable<ServiceProviderAccountEntity>()
.Where(x => x.ServiceProviderId == serviceProviderId && x.AppId == appId)
.Select(x => x.Id)
.FirstAsync();
}
/// <summary>
/// 通过服务商code获取服务商
/// </summary>
/// <param name="serviceProviderCode">服务商code</param>
/// <returns></returns>
public async Task<ServiceProviderDto> GetServiceProviderByCodeAsync(string serviceProviderCode)
{
return await Context.Queryable<ServiceProviderEntity>()
.Where(x => x.Code == serviceProviderCode).Select<ServiceProviderDto>()
.FirstAsync();
}
/// <summary>
/// 通过服务商Id获取服务商
/// </summary>
/// <param name="serviceProviderId">服务商Id</param>
/// <returns></returns>
public async Task<ServiceProviderDto> GetServiceProviderByIdAsync(int serviceProviderId)
{
return await Context.Queryable<ServiceProviderEntity>()
.Where(x => x.Id == serviceProviderId).Select<ServiceProviderDto>()
.FirstAsync();
}
/// <summary>
/// 通过账户id获取账户字段列表
/// </summary>
/// <param name="accountId">账户id</param>
/// <returns></returns>
public async Task<List<ServiceProviderAccountFieldWithValueDto>> GetAccountFieldListAsync(int accountId)
{
if (accountId == default) return new List<ServiceProviderAccountFieldWithValueDto>();
var query = Context.Queryable<ServiceProviderAccountFieldEntity>()
.LeftJoin<ServiceProviderAccountFieldValueEntity>((a, b) => a.Id == b.AccountFieldId);
return await query.Where((a, b) => b.AccountId == accountId)
.Select((a, b) => new ServiceProviderAccountFieldWithValueDto
{
FieldName = a.FieldName,
FieldValue = b.FieldValue
})
.ToListAsync();
}
/// <summary>
/// 查找app
/// </summary>
/// <param name="appKey"></param>
/// <param name="appSecret"></param>
/// <returns></returns>
public async Task<AppVO> FindAppAsync(string appKey, string appSecret)
{
return await Context.Queryable<AppEntity>()
.Where(x => x.AppKey == appKey && x.AppSecret == appSecret)
.Select<AppVO>()
.FirstAsync();
}
/// <summary>
/// 获取接口QPS
/// </summary>
/// <param name="appId"></param>
/// <param name="interfaceCode"></param>
/// <returns></returns>
public async Task<int> GetQpsAsync(int appId, string interfaceCode)
{
return await Context.Queryable<AppScopeEntity>()
.Where(x =>
x.AppId == appId && x.InterfaceCode == interfaceCode)
.Select(x => x.QPS)
.FirstAsync();
}
/// <summary>
/// 获取参数映射列表
/// </summary>
/// <param name="mapIds">映射id集合</param>
/// <param name="isInParaMap">是入参映射</param>
/// <returns></returns>
public async Task<IReadOnlyCollection<InterfaceParameterMapDto>> GetParameterMapListAsync(List<int> mapIds,
bool isInParaMap)
{
// tips这里要拿所有节点而非仅叶子因为要构建参数树
/*
SELECT `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` , CONCAT(d.Code, '.', c.Alias) AS `MapAlias` , `b`.`IsRequired` AS `IsRequired`
from t_interface_map t
LEFT JOIN `t_parameter` `b` ON ( `t`.`DownStreamId` = `b`.`InterfaceId` ) and b.IsInPara and `b`.`IsDeleted` = 0 -- AND ( `b`.`Type` <> 12 ) AND ( `b`.`Type` <> 10 )
Left JOIN `t_interface_map_detail` `a` ON ( `t`.`Id` = `a`.`InterfaceMapId` ) and b.id = a.ParaId and a.IsDeleted = 0
Left JOIN `t_parameter` `c` ON ( `a`.`MappedParaId` = `c`.`Id` ) AND ( `c`.`IsDeleted` = 0 )
Left JOIN t_interface d on c.interfaceid = d.id
WHERE t.id in (403) and t.IsDeleted = 0
ORDER BY `b`.`Sort` ASC
*/
var ids = mapIds.JoinAsString(",");
var isMultiMap = mapIds.Count > 1;
// 因为入参映射有多个 出参映射只有一个(挂在第一个映射)
return await Context.SqlQueryable<InterfaceParameterMapDto>(@$"
select `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` , {(isMultiMap ? "CONCAT(d.Code, '.', c.Alias)" : "c.Alias")} AS `MapAlias` , `b`.`IsRequired` AS `IsRequired`
from t_interface_map t
LEFT JOIN `t_parameter` `b` ON {(isInParaMap ? "t.DownStreamId" : "t.UpStreamId")} = `b`.`InterfaceId` and b.IsInPara = {isInParaMap} AND ( `b`.`IsDeleted` = 0 )
Left JOIN `t_interface_map_detail` `a` ON ( `t`.`Id` = `a`.`InterfaceMapId` ) and b.id = a.ParaId and a.IsDeleted = 0
Left JOIN `t_parameter` `c` ON ( `a`.`MappedParaId` = `c`.`Id` ) AND ( `c`.`IsDeleted` = 0 )
Left JOIN t_interface d on c.interfaceid = d.id
WHERE {(isInParaMap ? $"t.id in ({ids})" : $"t.id = {mapIds.First()}")} and t.IsDeleted = 0
ORDER BY `b`.`Sort` ASC").ToListAsync();
}
/// <summary>
/// 获取接口根据接口code
/// </summary>
/// <param name="interfaceCode"></param>
/// <returns></returns>
public async Task<InterfaceDto?> GetInterfaceByCodeAsync(string interfaceCode)
{
var res = await GetInterfaceByCodesAsync(interfaceCode);
return res.FirstOrDefault();
}
/// <summary>
/// 构建转发核心上下文
/// </summary>
/// <param name="systemInterface"></param>
/// <param name="serviceProvider"></param>
/// <returns></returns>
/// <exception cref="BusinessException"></exception>
public async Task<ForwardCoreContextCache> BuildForwardCoreContext(InterfaceDto systemInterface,
ServiceProviderDto serviceProvider)
{
var maps = await Context.Queryable<InterfaceMapEntity>()
.Where(x => x.UpStreamCode == systemInterface.Code && x.ServiceProviderId == serviceProvider.Id)
.Select(x => new { x.Id, x.DownStreamCode, x.PrefixScript, x.PostfixScript })
.ToArrayAsync();
if (maps == null || maps.Length == 0) throw new BusinessException(message: "映射不存在");
var downStreamIds = maps.Select(x => x.DownStreamCode).ToArray();
var targetInterfaceList = await GetInterfaceByCodesAsync(downStreamIds);
if (targetInterfaceList == null || targetInterfaceList.Count != downStreamIds.Length)
throw new BusinessException(message: "服务商一个或多个接口不存在");
var mapIds = maps.Select(x => x.Id).ToList();
var context = new ForwardCoreContextCache
{
OriginalInterface = systemInterface,
TargetServiceProvider = serviceProvider,
ServiceProviderAuthConfigs = await Context.Queryable<ServiceProviderAuthConfigEntity>()
.LeftJoin<ParameterEntity>((a, b) => a.ParameterId == b.Id)
.Where(a => a.ServiceProviderId == serviceProvider.Id)
.Select((a, b) => new ServiceProviderAuthConfigDto
{
Flag = a.Flag,
ParameterAlias = b.Alias,
Value1 = a.Value1,
Value2 = a.Value2,
Value3 = a.Value3
})
.ToListAsync(),
OutParamTreeList = JsonHelper.BuildTreeList(
await GetParameterMapListAsync(mapIds, false)
) // 构建系统返参数树形结构
};
if (serviceProvider.AuthInterfaceCode != null)
{
var authInterface = await GetInterfaceByCodeAsync(serviceProvider.AuthInterfaceCode);
if (authInterface == null)
{
throw new BusinessException($"授权接口{serviceProvider.AuthInterfaceCode}不存在");
}
context.ServiceProviderAuthInterface = new TargetInterfaceSummary
{
TargetInterface = authInterface,
FixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, authInterface.Id),
ReturnConfigList = await GetInterfaceReturnConfigListAsync(authInterface.Id),
FormFieldList = await GetFormFieldListAsync(authInterface.Id),
};
}
var inParaMaps = await GetParameterMapListAsync(mapIds, true);
foreach (var map in maps)
{
var targetInterface = targetInterfaceList.First(x => map.DownStreamCode == x.Code);
var items = inParaMaps.Where(x => x.InterfaceId == targetInterface.Id).ToList();
var fixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, targetInterface.Id);
if (targetInterface.MappedParamType == ParameterType.Array)
{
var rootLen = items.First(x => x.PId == 0).Alias.Length;
foreach (var item in fixedFieldList.Where(x => x.FieldPosition == FieldPosition.Body))
{
// 去除固定参数[*]前面的路径
item.FieldName = item.FieldName[rootLen..];
}
}
context.TargetInterfaces.Add(new TargetInterfaceSummary
{
TargetInterface = targetInterface,
InParamTreeList = JsonHelper.BuildTreeList(items), // 构建目标接口入参树形结构
FixedFieldList = fixedFieldList,
ReturnConfigList = await GetInterfaceReturnConfigListAsync(targetInterface.Id),
PrefixScript = map.PrefixScript,
PostfixScript = map.PostfixScript,
FormFieldList = await GetFormFieldListAsync(targetInterface.Id),
});
}
return context;
}
private async Task<List<InterfaceFormFieldDto>> GetFormFieldListAsync(int interfaceId)
{
return await Context.Queryable<FormParameterEntity>()
.Where(x => x.InterfaceId == interfaceId)
.Select<InterfaceFormFieldDto>()
.ToListAsync();
}
/// <summary>
/// 获取所有固定字段(服务商+接口)
/// </summary>
/// <param name="serviceProviderId">服务商id</param>
/// <param name="interfaceId">接口id</param>
/// <returns></returns>
private async Task<List<FixedFieldWithValueDto>> GetAllFixedFieldListAsync(int serviceProviderId,
int interfaceId)
{
var fixedFieldList = await Context.Queryable<FixedParameterEntity>()
.Where(a => a.ServiceProviderId == serviceProviderId || a.InterfaceId == interfaceId)
.Select(x => new
{
x.ServiceProviderId,
x.InterfaceId,
x.FieldName,
x.FieldValue,
x.FieldPositions,
x.Description
})
.ToListAsync();
// 接口字段
var list1 = from interfaceField in fixedFieldList.Where(x => x.InterfaceId == interfaceId)
from position in interfaceField.FieldPositions.Split(",").Select(Enum.Parse<FieldPosition>)
select new FixedFieldWithValueDto
{
FieldOwner = FieldOwner.Interface, FieldName = interfaceField.FieldName,
FieldValue = interfaceField.FieldValue, Description = interfaceField.Description,
FieldPosition = position,
};
// 接口不曾拥有的服务商参数
var list2 = from serviceProviderField in fixedFieldList.Where(x => x.ServiceProviderId == serviceProviderId)
from position in serviceProviderField.FieldPositions.Split(",")
.Select(Enum.Parse<FieldPosition>)
where !list1.Any(it => it.FieldName.Equals(serviceProviderField.FieldName) && it.FieldPosition == position)
select new FixedFieldWithValueDto
{
FieldOwner = FieldOwner.ServiceProvider, FieldName = serviceProviderField.FieldName,
FieldValue = serviceProviderField.FieldValue, Description = serviceProviderField.Description,
FieldPosition = position,
};
return list1.Concat(list2).ToList();
}
/// <summary>
/// 获取接口返回配置集合
/// </summary>
/// <param name="interfaceId">接口id</param>
/// <returns></returns>
private async Task<List<InterfaceReturnConfigDto>> GetInterfaceReturnConfigListAsync(int interfaceId)
{
return await Context.Queryable<InterfaceReturnConfigEntity>()
.LeftJoin<ParameterEntity>((a, b) => a.ParameterId == b.Id)
.Where(a => a.InterfaceId == interfaceId)
.Select((a, b) => new InterfaceReturnConfigDto
{
InterfaceId = a.InterfaceId,
ConfigType = a.ConfigType,
Path = b.Alias,
Value = a.Value,
}).ToListAsync();
}
/// <summary>
/// 获取接口根据接口code
/// </summary>
/// <param name="interfaceCodes"></param>
/// <returns></returns>
private async Task<List<InterfaceDto>> GetInterfaceByCodesAsync(params string[] interfaceCodes)
{
var query = Context.Queryable<InterfaceEntity, DictionaryEntity>(
(a, d) => new JoinQueryInfos(
JoinType.Left, a.RequestMethod == d.Id
))
.Where(a => interfaceCodes.Contains(a.Code) && a.IsDeleted == false)
.Filter(null, true)
.Select((a, d) =>
new InterfaceDto
{
Id = a.Id,
Name = a.Name,
ServiceProviderId = a.ServiceProviderId,
Code = a.Code,
RequestAddress = a.RequestAddress,
RequestProtocol = a.RequestProtocol,
ContentType = a.ContentType,
ResponseContentType = a.ResponseContentType,
RequestMethod = d.Name,
IsBatch = a.IsBatch,
Limit = a.Limit,
Qps = a.Qps,
FlowCode = a.FlowCode,
IsDisableAuth = a.IsDisableAuth,
MappedParamType = a.MappedParamType
});
return await query.ToListAsync();
}
}