353 lines
15 KiB
C#
353 lines
15 KiB
C#
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();
|
||
}
|
||
} |