50 changed files with 1054 additions and 0 deletions
@ -0,0 +1,14 @@ |
|||||
|
using AutoMapper; |
||||
|
using EShopOnAbp.CatalogService.Grpc; |
||||
|
using EShopOnAbp.CatalogService.Products; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService; |
||||
|
|
||||
|
public class BasketServiceApplicationAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public BasketServiceApplicationAutoMapperProfile() |
||||
|
{ |
||||
|
CreateMap<ProductEto, ProductDto>(); |
||||
|
CreateMap<ProductResponse, ProductDto>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,184 @@ |
|||||
|
using EShopOnAbp.BasketService.Entities; |
||||
|
using EShopOnAbp.BasketService.Localization; |
||||
|
using EShopOnAbp.CatalogService.Grpc; |
||||
|
using EShopOnAbp.Shared.Hosting.AspNetCore; |
||||
|
using EShopOnAbp.Shared.Hosting.Microservices; |
||||
|
using Microsoft.AspNetCore.Cors; |
||||
|
using Microsoft.Extensions.Caching.Distributed; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc.AntiForgery; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Localization.ExceptionHandling; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Validation.Localization; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
)] |
||||
|
public class BasketServiceModule : AbpModule |
||||
|
{ |
||||
|
public const string RemoteServiceName = "Basket"; |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
|
||||
|
ConfigureAutoMapper(); |
||||
|
ConfigureGrpc(context); |
||||
|
ConfigureDistributedCache(); |
||||
|
ConfigureVirtualFileSystem(); |
||||
|
ConfigureLocalization(); |
||||
|
ConfigureHttpApiProxy(context); |
||||
|
ConfigureAuthentication(context, configuration); |
||||
|
} |
||||
|
|
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
var env = context.GetEnvironment(); |
||||
|
|
||||
|
if (env.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseDeveloperExceptionPage(); |
||||
|
} |
||||
|
|
||||
|
app.UseCorrelationId(); |
||||
|
app.UseCors(); |
||||
|
app.UseAbpRequestLocalization(); |
||||
|
app.UseStaticFiles(); |
||||
|
app.UseRouting(); |
||||
|
app.UseAuthentication(); |
||||
|
app.UseAbpClaimsMap(); |
||||
|
app.UseAuthorization(); |
||||
|
app.UseSwagger(); |
||||
|
app.UseSwaggerUI(options => |
||||
|
{ |
||||
|
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>(); |
||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Basket Service API"); |
||||
|
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); |
||||
|
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]); |
||||
|
}); |
||||
|
app.UseAbpSerilogEnrichers(); |
||||
|
app.UseAuditing(); |
||||
|
app.UseUnitOfWork(); |
||||
|
app.UseConfiguredEndpoints(); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) |
||||
|
{ |
||||
|
JwtBearerConfigurationHelper.Configure(context, "BasketService"); |
||||
|
|
||||
|
SwaggerWithAuthConfigurationHelper.Configure( |
||||
|
context: context, |
||||
|
authority: configuration["AuthServer:Authority"], |
||||
|
scopes: new |
||||
|
Dictionary<string, string> /* Requested scopes for authorization code request and descriptions for swagger UI only */ |
||||
|
{ |
||||
|
{"BasketService", "Basket Service API"} |
||||
|
}, |
||||
|
apiTitle: "Basket Service API" |
||||
|
); |
||||
|
|
||||
|
context.Services.AddCors(options => |
||||
|
{ |
||||
|
options.AddDefaultPolicy(builder => |
||||
|
{ |
||||
|
builder |
||||
|
.WithOrigins( |
||||
|
configuration["App:CorsOrigins"] |
||||
|
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
||||
|
.Select(o => o.Trim().RemovePostFix("/")) |
||||
|
.ToArray() |
||||
|
) |
||||
|
.WithAbpExposedHeaders() |
||||
|
.SetIsOriginAllowedToAllowWildcardSubdomains() |
||||
|
.AllowAnyHeader() |
||||
|
.AllowAnyMethod() |
||||
|
.AllowCredentials(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; }); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureHttpApiProxy(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddStaticHttpClientProxies( |
||||
|
typeof(BasketServiceApplicationContractsModule).Assembly, |
||||
|
RemoteServiceName |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureGrpc(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddGrpcClient<ProductPublic.ProductPublicClient>((services, options) => |
||||
|
{ |
||||
|
var remoteServiceOptions = services.GetRequiredService<IOptionsMonitor<AbpRemoteServiceOptions>>().CurrentValue; |
||||
|
var catalogServiceConfiguration = remoteServiceOptions.RemoteServices.GetConfigurationOrDefault("Catalog"); |
||||
|
var catalogGrpcUrl = catalogServiceConfiguration.GetOrDefault("GrpcUrl"); |
||||
|
|
||||
|
options.Address = new Uri(catalogGrpcUrl); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAutoMapper() |
||||
|
{ |
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddMaps<BasketServiceApplicationModule>(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureDistributedCache() |
||||
|
{ |
||||
|
Configure<AbpDistributedCacheOptions>(options => |
||||
|
{ |
||||
|
options.CacheConfigurators.Add(cacheName => |
||||
|
{ |
||||
|
if (cacheName == CacheNameAttribute.GetCacheName(typeof(Basket))) |
||||
|
{ |
||||
|
return new DistributedCacheEntryOptions |
||||
|
{ |
||||
|
SlidingExpiration = TimeSpan.FromDays(7) |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureVirtualFileSystem() |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<BasketServiceModule>(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureLocalization() |
||||
|
{ |
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Add<BasketServiceResource>("en") |
||||
|
.AddBaseTypes(typeof(AbpValidationResource)) |
||||
|
.AddVirtualJson("/Localization/BasketService"); |
||||
|
|
||||
|
options.DefaultResourceType = typeof(BasketServiceResource); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpExceptionLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.MapCodeNamespace("BasketService", typeof(BasketServiceResource)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Controllers; |
||||
|
|
||||
|
public class HomeController : AbpController |
||||
|
{ |
||||
|
public ActionResult Index() |
||||
|
{ |
||||
|
return Redirect("~/swagger"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<!-- DOMAIN SHARED --> |
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Validation" Version="5.1.2" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.0" /> |
||||
|
<ProjectReference Include="..\..\..\ordering\src\EShopOnAbp.OrderingService.Domain.Shared\EShopOnAbp.OrderingService.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Localization\BasketService\*.json" /> |
||||
|
<Content Remove="Localization\BasketService\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- DOMAIN --> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain.Shared\EShopOnAbp.BasketService.Domain.Shared.csproj" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="5.1.2" /> |
||||
|
<PackageReference Include="Volo.Abp.Caching" Version="5.1.2" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- APPLICATION CONTRACTS --> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain.Shared\EShopOnAbp.BasketService.Domain.Shared.csproj" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="5.1.2" /> |
||||
|
<PackageReference Include="Volo.Abp.Authorization" Version="5.1.2" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- APPLICATION --> |
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AutoMapper" Version="5.1.2" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="5.1.2" /> |
||||
|
<PackageReference Include="Google.Protobuf" Version="3.19.3" /> |
||||
|
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.42.0" /> |
||||
|
<PackageReference Include="Grpc.Tools" Version="2.42.0" PrivateAssets="All" /> |
||||
|
<Protobuf Include="..\..\..\catalog\src\EShopOnAbp.CatalogService.Application.Contracts\Protos\product.proto" GrpcServices="Client" /> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain\EShopOnAbp.BasketService.Domain.csproj" /> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Application.Contracts\EShopOnAbp.BasketService.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\catalog\src\EShopOnAbp.CatalogService.HttpApi.Client\EShopOnAbp.CatalogService.HttpApi.Client.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- HTTP API --> |
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="5.1.2" /> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Application.Contracts\EShopOnAbp.BasketService.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- HTTP API HOST --> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.Application\EShopOnAbp.BasketService.Application.csproj" /> |
||||
|
<ProjectReference Include="..\EShopOnAbp.BasketService.HttpApi\EShopOnAbp.BasketService.HttpApi.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\shared\EShopOnAbp.Shared.Hosting.Microservices\EShopOnAbp.Shared.Hosting.Microservices.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Compile Remove="Logs\**" /> |
||||
|
<Content Remove="Logs\**" /> |
||||
|
<EmbeddedResource Remove="Logs\**" /> |
||||
|
<None Remove="Logs\**" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,77 @@ |
|||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Entities; |
||||
|
|
||||
|
public class Basket : AggregateRoot<Guid> |
||||
|
{ |
||||
|
public List<BasketItem> Items { get; set; } |
||||
|
|
||||
|
private Basket() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Basket(Guid id) |
||||
|
: base(id) |
||||
|
{ |
||||
|
Items = new List<BasketItem>(); |
||||
|
} |
||||
|
|
||||
|
public void AddProduct(Guid productId, int count = 1) |
||||
|
{ |
||||
|
if (count < 1) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException(nameof(count), "Product count should be 1 or more!"); |
||||
|
} |
||||
|
|
||||
|
var item = Items.FirstOrDefault(x => x.ProductId == productId); |
||||
|
if (item == null) |
||||
|
{ |
||||
|
Items.Add(new BasketItem(productId, count)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
item.Count += count; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void RemoveProduct(Guid productId, int? count = null) |
||||
|
{ |
||||
|
if (count is < 1) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException(nameof(count), "Product count should be null, 1 or more!"); |
||||
|
} |
||||
|
|
||||
|
var item = Items.FirstOrDefault(x => x.ProductId == productId); |
||||
|
if (item == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (count == null || item.Count <= count) |
||||
|
{ |
||||
|
Items.Remove(item); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
item.Count -= count.Value; |
||||
|
} |
||||
|
|
||||
|
public int GetProductCount(Guid productId) |
||||
|
{ |
||||
|
var item = Items.FirstOrDefault(x => x.ProductId == productId); |
||||
|
return item?.Count ?? 0; |
||||
|
} |
||||
|
|
||||
|
public void Clear() |
||||
|
{ |
||||
|
Items.Clear(); |
||||
|
} |
||||
|
|
||||
|
public void Merge(Basket basket) |
||||
|
{ |
||||
|
foreach (var item in basket.Items) |
||||
|
{ |
||||
|
AddProduct(item.ProductId, item.Count); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Entities; |
||||
|
|
||||
|
public class BasketItem |
||||
|
{ |
||||
|
public Guid ProductId { get; private set; } |
||||
|
public int Count { get; internal set; } |
||||
|
|
||||
|
private BasketItem() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public BasketItem(Guid productId, int count = 1) |
||||
|
{ |
||||
|
ProductId = productId; |
||||
|
Count = count; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Entities; |
||||
|
|
||||
|
public class BasketProductUpdatedEto |
||||
|
{ |
||||
|
public Guid ProductId { get; set; } |
||||
|
public string ProductName { get; set; } |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using Volo.Abp.Caching; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Entities; |
||||
|
|
||||
|
public class BasketRepository : IBasketRepository |
||||
|
{ |
||||
|
private readonly IDistributedCache<Basket, Guid> _cache; |
||||
|
|
||||
|
public BasketRepository(IDistributedCache<Basket, Guid> cache) |
||||
|
{ |
||||
|
_cache = cache; |
||||
|
} |
||||
|
|
||||
|
public async Task<Basket> GetAsync(Guid id) |
||||
|
{ |
||||
|
return await _cache.GetOrAddAsync(id, () => Task.FromResult(new Basket(id))); |
||||
|
} |
||||
|
|
||||
|
public async Task UpdateAsync(Basket basket) |
||||
|
{ |
||||
|
await _cache.SetAsync(basket.Id, basket); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Entities; |
||||
|
|
||||
|
public interface IBasketRepository : IRepository |
||||
|
{ |
||||
|
Task<Basket> GetAsync(Guid id); |
||||
|
|
||||
|
Task UpdateAsync(Basket basket); |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using EShopOnAbp.OrderingService.Orders; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Entities.Orders |
||||
|
{ |
||||
|
public class OrderPlacedEventHandler : IDistributedEventHandler<OrderPlacedEto>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IBasketRepository _basketRepository; |
||||
|
|
||||
|
public OrderPlacedEventHandler(IBasketRepository basketRepository) |
||||
|
{ |
||||
|
_basketRepository = basketRepository; |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public async Task HandleEventAsync(OrderPlacedEto eventData) |
||||
|
{ |
||||
|
var basket = await _basketRepository.GetAsync(eventData.Buyer.BuyerId.GetValueOrDefault()); |
||||
|
basket.Clear(); |
||||
|
await _basketRepository.UpdateAsync(basket); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "ar", |
||||
|
"texts": { |
||||
|
"Menu:Home": "الرئيسية", |
||||
|
"Welcome": "مرحبا", |
||||
|
"LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "cs", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Úvod", |
||||
|
"Welcome": "Vítejte", |
||||
|
"LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "de-DE", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Willkommen", |
||||
|
"LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "en-GB", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Welcome", |
||||
|
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Welcome", |
||||
|
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.", |
||||
|
"Toolbar:Cart": "My Cart", |
||||
|
"Toolbar:BasketNotLoaded": "Couldn't Load!", |
||||
|
"Toolbar:CartEmpty": "Cart is Empty!", |
||||
|
"ProductNotFound": "Could not find the product!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "es", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Inicio", |
||||
|
"Welcome": "Bienvenido", |
||||
|
"LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "fi", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Koti", |
||||
|
"Welcome": "Tervetuloa", |
||||
|
"LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "fr", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Accueil", |
||||
|
"Welcome": "Bienvenue", |
||||
|
"LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "hi", |
||||
|
"texts": { |
||||
|
"Menu:Home": "घर", |
||||
|
"Welcome": "स्वागत हे", |
||||
|
"LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "hu", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Kezdőlap", |
||||
|
"Welcome": "Üdvözlöm", |
||||
|
"LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "it", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Benvenuto", |
||||
|
"LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "nl", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Welkom", |
||||
|
"LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "pl-PL", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Home", |
||||
|
"Welcome": "Witaj", |
||||
|
"LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "pt-BR", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Principal", |
||||
|
"Welcome": "Seja bem-vindo!", |
||||
|
"LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "ro-RO", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Acasă", |
||||
|
"Welcome": "Bun venit", |
||||
|
"LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "ru", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Главная", |
||||
|
"Welcome": "Добро пожаловать", |
||||
|
"LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "sk", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Domov", |
||||
|
"Welcome": "Vitajte", |
||||
|
"LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "sl", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Domov", |
||||
|
"Welcome": "Dobrodošli", |
||||
|
"LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"culture": "tr", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Ana sayfa", |
||||
|
"Welcome": "Hoşgeldiniz", |
||||
|
"LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz.", |
||||
|
"Toolbar:Cart": "Sepetim", |
||||
|
"Toolbar:BasketNotLoaded": "Sepet Hatası!", |
||||
|
"Toolbar:CartEmpty": "Sepetiniz Boş", |
||||
|
"ProductNotFound": "Bu ürün bulunamadı!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "vi", |
||||
|
"texts": { |
||||
|
"Menu:Home": "Trang chủ", |
||||
|
"Welcome": "Chào mừng bạn", |
||||
|
"LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Menu:Home": "首页", |
||||
|
"Welcome": "欢迎", |
||||
|
"LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 abp.io.", |
||||
|
"Toolbar:Cart": "我的购物车", |
||||
|
"Toolbar:BasketNotLoaded": "无法加载!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hant", |
||||
|
"texts": { |
||||
|
"Menu:Home": "首頁", |
||||
|
"Welcome": "歡迎", |
||||
|
"LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Localization |
||||
|
{ |
||||
|
[LocalizationResourceName("BasketService")] |
||||
|
public class BasketServiceResource |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
var app = builder.Build(); |
||||
|
|
||||
|
app.MapGet("/", () => "Hello World!"); |
||||
|
|
||||
|
app.Run(); |
||||
@ -0,0 +1,28 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:43756", |
||||
|
"sslPort": 44365 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"EShopOnAbp.BasketService": { |
||||
|
"commandName": "Project", |
||||
|
"dotnetRunMessages": true, |
||||
|
"launchBrowser": true, |
||||
|
"applicationUrl": "https://localhost:7198;http://localhost:5198", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,124 @@ |
|||||
|
using EShopOnAbp.BasketService.Entities; |
||||
|
using EShopOnAbp.BasketService.Localization; |
||||
|
using EShopOnAbp.BasketService.Services.Dtos; |
||||
|
using EShopOnAbp.CatalogService.Products; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services; |
||||
|
|
||||
|
public class BasketAppService : ApplicationService, IBasketAppService |
||||
|
{ |
||||
|
private readonly IBasketRepository _basketRepository; |
||||
|
private readonly IBasketProductService _basketProductService; |
||||
|
|
||||
|
public BasketAppService( |
||||
|
IBasketRepository basketRepository, |
||||
|
IBasketProductService basketProductService) |
||||
|
{ |
||||
|
_basketRepository = basketRepository; |
||||
|
_basketProductService = basketProductService; |
||||
|
LocalizationResource = typeof(BasketServiceResource); |
||||
|
} |
||||
|
|
||||
|
public async Task<BasketDto> GetAsync(Guid? anonymousUserId) |
||||
|
{ |
||||
|
if (anonymousUserId != null && CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var userBasket = await _basketRepository.GetAsync(CurrentUser.GetId()); |
||||
|
var anonymousUserBasket = await _basketRepository.GetAsync(anonymousUserId.Value); |
||||
|
|
||||
|
userBasket.Merge(anonymousUserBasket); |
||||
|
await _basketRepository.UpdateAsync(userBasket); |
||||
|
|
||||
|
anonymousUserBasket.Clear(); |
||||
|
await _basketRepository.UpdateAsync(anonymousUserBasket); |
||||
|
|
||||
|
return await GetBasketDtoAsync(userBasket); |
||||
|
} |
||||
|
|
||||
|
if (anonymousUserId != null && !CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
return await GetBasketDtoAsync(await _basketRepository.GetAsync(anonymousUserId.Value)); |
||||
|
} |
||||
|
|
||||
|
return await GetBasketDtoAsync(await _basketRepository.GetAsync(CurrentUser.GetId())); |
||||
|
} |
||||
|
|
||||
|
public async Task<BasketDto> AddProductAsync(AddProductDto input) |
||||
|
{ |
||||
|
Guid userId = CurrentUser.IsAuthenticated ? CurrentUser.GetId() : input.AnonymousId.GetValueOrDefault(); |
||||
|
|
||||
|
var basket = await _basketRepository.GetAsync(userId); |
||||
|
var product = await _basketProductService.GetAsync(input.ProductId); |
||||
|
|
||||
|
if (basket.GetProductCount(product.Id) >= product.StockCount) |
||||
|
{ |
||||
|
throw new UserFriendlyException("There is not enough product in stock, sorry :("); |
||||
|
} |
||||
|
|
||||
|
basket.AddProduct(product.Id); |
||||
|
|
||||
|
await _basketRepository.UpdateAsync(basket); |
||||
|
|
||||
|
return await GetBasketDtoAsync(basket); |
||||
|
} |
||||
|
|
||||
|
public async Task<BasketDto> RemoveProductAsync(RemoveProductDto input) |
||||
|
{ |
||||
|
Guid userId = CurrentUser.IsAuthenticated ? CurrentUser.GetId() : input.AnonymousId.GetValueOrDefault(); |
||||
|
|
||||
|
var basket = await _basketRepository.GetAsync(userId); |
||||
|
var product = await _basketProductService.GetAsync(input.ProductId); |
||||
|
|
||||
|
basket.RemoveProduct(product.Id, input.Count); |
||||
|
|
||||
|
await _basketRepository.UpdateAsync(basket); |
||||
|
|
||||
|
return await GetBasketDtoAsync(basket); |
||||
|
} |
||||
|
|
||||
|
private async Task<BasketDto> GetBasketDtoAsync(Basket basket) |
||||
|
{ |
||||
|
var products = new Dictionary<Guid, ProductDto>(); |
||||
|
var basketDto = new BasketDto(); |
||||
|
var basketChanged = false; |
||||
|
|
||||
|
foreach (var basketItem in basket.Items) |
||||
|
{ |
||||
|
var productDto = products.GetOrDefault(basketItem.ProductId); |
||||
|
if (productDto == null) |
||||
|
{ |
||||
|
productDto = await _basketProductService.GetAsync(basketItem.ProductId); |
||||
|
products[productDto.Id] = productDto; |
||||
|
} |
||||
|
|
||||
|
//Removing the products if not available in the stock
|
||||
|
if (basketItem.Count > productDto.StockCount) |
||||
|
{ |
||||
|
basket.RemoveProduct(basketItem.ProductId, basketItem.Count - productDto.StockCount); |
||||
|
basketChanged = true; |
||||
|
} |
||||
|
|
||||
|
basketDto.Items.Add(new BasketItemDto |
||||
|
{ |
||||
|
ProductId = basketItem.ProductId, |
||||
|
Count = basketItem.Count, |
||||
|
ProductCode = productDto.Code, |
||||
|
ImageName = productDto.ImageName, |
||||
|
ProductName = productDto.Name, |
||||
|
TotalPrice = productDto.Price * basketItem.Count |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
basketDto.TotalPrice = basketDto.Items.Sum(x => x.TotalPrice); |
||||
|
|
||||
|
if (basketChanged) |
||||
|
{ |
||||
|
await _basketRepository.UpdateAsync(basket); |
||||
|
} |
||||
|
|
||||
|
return basketDto; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using EShopOnAbp.BasketService.Entities; |
||||
|
using EShopOnAbp.CatalogService.Products; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities.Events.Distributed; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.ObjectMapping; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services; |
||||
|
|
||||
|
public class BasketProductEventHandler : IDistributedEventHandler<EntityUpdatedEto<ProductEto>>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IDistributedCache<ProductDto, Guid> _cache; |
||||
|
private readonly IObjectMapper _objectMapper; |
||||
|
private readonly IDistributedEventBus _distributedEventBus; |
||||
|
|
||||
|
public BasketProductEventHandler( |
||||
|
IDistributedCache<ProductDto, Guid> cache, |
||||
|
IObjectMapper objectMapper, |
||||
|
IDistributedEventBus distributedEventBus) |
||||
|
{ |
||||
|
_cache = cache; |
||||
|
_objectMapper = objectMapper; |
||||
|
_distributedEventBus = distributedEventBus; |
||||
|
} |
||||
|
|
||||
|
public async Task HandleEventAsync(EntityUpdatedEto<ProductEto> eventData) |
||||
|
{ |
||||
|
var cachedProductDto = await _cache.GetAsync(eventData.Entity.Id); |
||||
|
if (cachedProductDto == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_objectMapper.Map(eventData.Entity, cachedProductDto); |
||||
|
|
||||
|
await _cache.SetAsync(eventData.Entity.Id, cachedProductDto); |
||||
|
|
||||
|
await _distributedEventBus.PublishAsync( |
||||
|
new BasketProductUpdatedEto |
||||
|
{ |
||||
|
ProductId = eventData.Entity.Id, |
||||
|
ProductName = eventData.Entity.Name |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using EShopOnAbp.CatalogService.Grpc; |
||||
|
using EShopOnAbp.CatalogService.Products; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.ObjectMapping; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services; |
||||
|
|
||||
|
public class BasketProductService : IBasketProductService, ITransientDependency |
||||
|
{ |
||||
|
private readonly IDistributedCache<ProductDto, Guid> _cache; |
||||
|
private readonly ILogger<BasketProductService> _logger; |
||||
|
private readonly IObjectMapper _mapper; |
||||
|
private readonly ProductPublic.ProductPublicClient _productPublicGrpcClient; |
||||
|
|
||||
|
public BasketProductService( |
||||
|
IDistributedCache<ProductDto, Guid> cache, |
||||
|
ILogger<BasketProductService> logger, |
||||
|
IObjectMapper mapper, |
||||
|
ProductPublic.ProductPublicClient productPublicGrpcClient) |
||||
|
{ |
||||
|
_cache = cache; |
||||
|
_logger = logger; |
||||
|
_mapper = mapper; |
||||
|
_productPublicGrpcClient = productPublicGrpcClient; |
||||
|
} |
||||
|
|
||||
|
public async Task<ProductDto> GetAsync(Guid productId) |
||||
|
{ |
||||
|
return await _cache.GetOrAddAsync( |
||||
|
productId, |
||||
|
() => GetProductAsync(productId) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private async Task<ProductDto> GetProductAsync(Guid productId) |
||||
|
{ |
||||
|
var request = new ProductRequest { Id = productId.ToString() }; |
||||
|
_logger.LogInformation("=== GRPC request {@request}", request); |
||||
|
var response = await _productPublicGrpcClient.GetByIdAsync(request); |
||||
|
_logger.LogInformation("=== GRPC response {@response}", response); |
||||
|
return _mapper.Map<ProductResponse, ProductDto>(response) ?? |
||||
|
throw new UserFriendlyException(BasketServiceDomainErrorCodes.ProductNotFound); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services.Dtos; |
||||
|
|
||||
|
public class AddProductDto : IHasAnonymousId |
||||
|
{ |
||||
|
public Guid ProductId { get; set; } |
||||
|
|
||||
|
[Range(1, int.MaxValue)] |
||||
|
public int Count { get; set; } = 1; |
||||
|
|
||||
|
public Guid? AnonymousId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Services.Dtos; |
||||
|
|
||||
|
public class BasketDto |
||||
|
{ |
||||
|
public float TotalPrice { get; set; } |
||||
|
public List<BasketItemDto> Items { get; set; } |
||||
|
|
||||
|
public BasketDto() |
||||
|
{ |
||||
|
Items = new List<BasketItemDto>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Services.Dtos; |
||||
|
|
||||
|
public class BasketItemDto |
||||
|
{ |
||||
|
public Guid ProductId { get; set; } |
||||
|
public string ProductName { get; set; } |
||||
|
public string ProductCode { get; set; } |
||||
|
public string ImageName { get; set; } |
||||
|
public int Count { get; set; } |
||||
|
public float TotalPrice { get; set; } |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Services.Dtos |
||||
|
{ |
||||
|
public interface IHasAnonymousId |
||||
|
{ |
||||
|
Guid? AnonymousId { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Services.Dtos; |
||||
|
|
||||
|
public class RemoveProductDto : IHasAnonymousId |
||||
|
{ |
||||
|
public Guid ProductId { get; set; } |
||||
|
|
||||
|
public int? Count { get; set; } |
||||
|
|
||||
|
public Guid? AnonymousId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using EShopOnAbp.BasketService.Services.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services; |
||||
|
|
||||
|
public interface IBasketAppService : IApplicationService |
||||
|
{ |
||||
|
Task<BasketDto> GetAsync(Guid? anonymousUserId); |
||||
|
Task<BasketDto> AddProductAsync(AddProductDto input); |
||||
|
Task<BasketDto> RemoveProductAsync(RemoveProductDto input); |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using EShopOnAbp.CatalogService.Products; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService; |
||||
|
|
||||
|
public interface IBasketProductService |
||||
|
{ |
||||
|
[ItemNotNull] |
||||
|
Task<ProductDto> GetAsync(Guid productId); |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using EShopOnAbp.BasketService.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace EShopOnAbp.BasketService.Services.Permissions |
||||
|
{ |
||||
|
public class BasketServicePermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var myGroup = context.AddGroup(BasketServicePermissions.GroupName); |
||||
|
//Define your own permissions here. Example:
|
||||
|
//myGroup.AddPermission(BasketServicePermissions.MyPermission1, L("Permission:MyPermission1"));
|
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<BasketServiceResource>(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace EShopOnAbp.BasketService.Services.Permissions |
||||
|
{ |
||||
|
public static class BasketServicePermissions |
||||
|
{ |
||||
|
public const string GroupName = "BasketService"; |
||||
|
|
||||
|
//Add your own permission names. Example:
|
||||
|
//public const string MyPermission1 = GroupName + ".MyPermission1";
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Information", |
||||
|
"Microsoft.AspNetCore": "Warning" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
{ |
||||
|
"App": { |
||||
|
"SelfUrl": "https://localhost:44355", |
||||
|
"CorsOrigins": "https://localhost:44372,https://localhost:44373,https://localhost:44335" |
||||
|
}, |
||||
|
"AuthServer": { |
||||
|
"Authority": "https://localhost:44330", |
||||
|
"RequireHttpsMetadata": "true", |
||||
|
"SwaggerClientId": "WebGateway_Swagger", |
||||
|
"SwaggerClientSecret": "1q2w3e*" |
||||
|
}, |
||||
|
"RemoteServices": { |
||||
|
"Catalog": { |
||||
|
"BaseUrl": "https://localhost:44354/", |
||||
|
"GrpcUrl": "http://localhost:81" |
||||
|
} |
||||
|
}, |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Information", |
||||
|
"Microsoft": "Warning", |
||||
|
"Microsoft.Hosting.Lifetime": "Information" |
||||
|
} |
||||
|
}, |
||||
|
"AllowedHosts": "*", |
||||
|
"ConnectionStrings": { |
||||
|
"AdministrationService": "User ID=postgres;Password=myPassw0rd;Host=localhost;Port=5432;Database=EShopOnAbp_Administration;Pooling=false;" |
||||
|
}, |
||||
|
"StringEncryption": { |
||||
|
"DefaultPassPhrase": "3PfxLgcuymUUbihz" |
||||
|
}, |
||||
|
"Redis": { |
||||
|
"Configuration": "localhost:6379" |
||||
|
}, |
||||
|
"RabbitMQ": { |
||||
|
"Connections": { |
||||
|
"Default": { |
||||
|
"HostName": "localhost" |
||||
|
} |
||||
|
}, |
||||
|
"EventBus": { |
||||
|
"ClientName": "EShopOnAbp_BasketService", |
||||
|
"ExchangeName": "EShopOnAbp" |
||||
|
} |
||||
|
}, |
||||
|
"ElasticSearch": { |
||||
|
"Url": "http://localhost:9200" |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue