feat : add version 0.19.22.38 , fix zarinpall issue

release
Amir Hossein Khademi 2024-04-03 10:40:41 +03:30
parent caf1bdd904
commit 5858cd3236
16 changed files with 7016 additions and 15 deletions

View File

@ -1 +1 @@
0.17.22.37
0.19.22.38

View File

@ -0,0 +1,23 @@
namespace NetinaShop.Api.Controller;
public class DistrictController : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("District")
.MapGroup("api/district");
group.MapGet("city", GetCitiesAsync)
.WithDisplayName("Get Cities")
.HasApiVersion(1.0);
group.MapGet("province", GetProvincesAsync)
.WithDisplayName("Get Cities")
.HasApiVersion(1.0);
}
private async Task<IResult> GetCitiesAsync([FromServices]IDistrictService districtService, [FromQuery] int? provinceId = null, CancellationToken cancellationToken = default)
=> TypedResults.Ok(districtService.GetCitiesAsync(provinceId));
private async Task<IResult> GetProvincesAsync([FromServices] IDistrictService districtService, CancellationToken cancellationToken = default)
=> TypedResults.Ok(districtService.GetProvincesAsync());
}

View File

@ -16,7 +16,6 @@ if (builder.Environment.IsProduction())
var configuration = builder.Configuration;
var siteSetting = configuration.GetSection(nameof(SiteSettings)).Get<SiteSettings>();
builder.Services.Configure<SiteSettings>(configuration.GetSection(nameof(SiteSettings)));
builder.Services.Configure<ShopSettings>(configuration.GetSection(nameof(ShopSettings)));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
[
{
"id": 1,
"name": "آذربایجان شرقی",
"slug": "آذربایجان-شرقی",
"tel_prefix": "041"
},
{
"id": 2,
"name": "آذربایجان غربی",
"slug": "آذربایجان-غربی",
"tel_prefix": "044"
},
{
"id": 3,
"name": "اردبیل",
"slug": "اردبیل",
"tel_prefix": "045"
},
{
"id": 4,
"name": "اصفهان",
"slug": "اصفهان",
"tel_prefix": "031"
},
{
"id": 5,
"name": "البرز",
"slug": "البرز",
"tel_prefix": "026"
},
{
"id": 6,
"name": "ایلام",
"slug": "ایلام",
"tel_prefix": "084"
},
{
"id": 7,
"name": "بوشهر",
"slug": "بوشهر",
"tel_prefix": "077"
},
{
"id": 8,
"name": "تهران",
"slug": "تهران",
"tel_prefix": "021"
},
{
"id": 9,
"name": "چهارمحال و بختیاری",
"slug": "چهارمحال-بختیاری",
"tel_prefix": "038"
},
{
"id": 10,
"name": "خراسان جنوبی",
"slug": "خراسان-جنوبی",
"tel_prefix": "056"
},
{
"id": 11,
"name": "خراسان رضوی",
"slug": "خراسان-رضوی",
"tel_prefix": "051"
},
{
"id": 12,
"name": "خراسان شمالی",
"slug": "خراسان-شمالی",
"tel_prefix": "058"
},
{
"id": 13,
"name": "خوزستان",
"slug": "خوزستان",
"tel_prefix": "061"
},
{
"id": 14,
"name": "زنجان",
"slug": "زنجان",
"tel_prefix": "024"
},
{
"id": 15,
"name": "سمنان",
"slug": "سمنان",
"tel_prefix": "023"
},
{
"id": 16,
"name": "سیستان و بلوچستان",
"slug": "سیستان-بلوچستان",
"tel_prefix": "054"
},
{
"id": 17,
"name": "فارس",
"slug": "فارس",
"tel_prefix": "071"
},
{
"id": 18,
"name": "قزوین",
"slug": "قزوین",
"tel_prefix": "028"
},
{
"id": 19,
"name": "قم",
"slug": "قم",
"tel_prefix": "025"
},
{
"id": 20,
"name": "کردستان",
"slug": "کردستان",
"tel_prefix": "087"
},
{
"id": 21,
"name": "کرمان",
"slug": "کرمان",
"tel_prefix": "034"
},
{
"id": 22,
"name": "کرمانشاه",
"slug": "کرمانشاه",
"tel_prefix": "083"
},
{
"id": 23,
"name": "کهگیلویه و بویراحمد",
"slug": "کهگیلویه-بویراحمد",
"tel_prefix": "074"
},
{
"id": 24,
"name": "گلستان",
"slug": "گلستان",
"tel_prefix": "017"
},
{
"id": 25,
"name": "لرستان",
"slug": "لرستان",
"tel_prefix": "066"
},
{
"id": 26,
"name": "گیلان",
"slug": "گیلان",
"tel_prefix": "013"
},
{
"id": 27,
"name": "مازندران",
"slug": "مازندران",
"tel_prefix": "011"
},
{
"id": 28,
"name": "مرکزی",
"slug": "مرکزی",
"tel_prefix": "086"
},
{
"id": 29,
"name": "هرمزگان",
"slug": "هرمزگان",
"tel_prefix": "076"
},
{
"id": 30,
"name": "همدان",
"slug": "همدان",
"tel_prefix": "081"
},
{
"id": 31,
"name": "یزد",
"slug": "یزد",
"tel_prefix": "035"
}
]

View File

@ -0,0 +1,9 @@
using NetinaShop.Domain.Models.Districts;
namespace NetinaShop.Core.Abstracts;
public interface IDistrictService : IScopedDependency
{
public List<City> GetCitiesAsync(int? provinceId = null);
public List<Province> GetProvincesAsync();
}

View File

@ -4,13 +4,11 @@ public class CalculateOrderCommandHandler : IRequestHandler<CalculateOrderComman
{
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
private readonly ShopSettings _shopSettings;
public CalculateOrderCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator, IOptionsSnapshot<ShopSettings> snapshot)
public CalculateOrderCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
_shopSettings = snapshot.Value;
}
public async Task<Order> Handle(CalculateOrderCommand request, CancellationToken cancellationToken)

View File

@ -5,4 +5,5 @@ public class PaymentSetting
public string ZarinPalApiKey { get; set; } = string.Empty;
public string PayPalApiKey { get; set; } = string.Empty;
public string BehPardakhtApiKey { get; set; } = string.Empty;
public string Shaba { get; set; } = string.Empty;
}

View File

@ -6,9 +6,15 @@ public class ShopSetting
public string Description { get; set; } = string.Empty;
public string Slogan { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public int CityId { get; set; }
public string Province { get; set; } = string.Empty;
public int ProvinceId { get; set; }
public double LocationLat { get; set; }
public double LocationLon { get; set; }
public string ENamad { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public string SupportPhoneNumber { get; set; } = string.Empty;
public string SupportPhoneNumber { get; set; } = string.Empty;
public double TaxesFee { get; set; }
public double ServiceFee { get; set; }
public bool ServiceIsPercent { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace NetinaShop.Domain.Models.Districts;
public class City
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Slug { get; set; } = string.Empty;
public int province_id { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace NetinaShop.Domain.Models.Districts;
public class Province
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Slug { get; set; } = string.Empty;
public string tel_prefix { get; set; } = string.Empty;
}

View File

@ -1,11 +1,5 @@
namespace NetinaShop.Domain.Models.Settings;
public class ShopSettings
{
public double TaxesFee { get; set; }
public double ServiceFee { get; set; }
public bool ServiceIsPercent { get; set; }
}
public class SiteSettings
{
public JwtSettings JwtSettings { get; set; } = new JwtSettings();

View File

@ -39,6 +39,7 @@
<Folder Include="Dtos\FilterDtos\" />
<Folder Include="Dtos\DashboardDtos\" />
<Folder Include="Entities\StorageFiles\" />
<Folder Include="Models\Districts\" />
<Folder Include="Models\Settings\" />
</ItemGroup>

View File

@ -3,5 +3,6 @@
public static class DirectoryAddress
{
private static string _baseDire = $"{Directory.GetCurrentDirectory()}/wwwroot";
public static string BaseDire = _baseDire ;
public static string Logs = $"{_baseDire}/logs";
}

View File

@ -0,0 +1,30 @@
using NetinaShop.Domain.Models.Districts;
using NetinaShop.Infrastructure.Models;
using Newtonsoft.Json;
namespace NetinaShop.Infrastructure.Services;
public class DistrictService : IDistrictService
{
public List<City> GetCitiesAsync(int? provinceId = null)
{
var cityList = File.ReadAllText(Path.Combine(DirectoryAddress.BaseDire, "cities.json"));
var cities = JsonConvert.DeserializeObject<List<City>>(cityList);
if (cities == null)
throw new AppException("City json is null");
if (provinceId != null)
return cities.Where(c => c.province_id == provinceId.Value).ToList();
return cities;
}
public List<Province> GetProvincesAsync()
{
var provinceList = File.ReadAllText(Path.Combine(DirectoryAddress.BaseDire, "provinces.json"));
var provinces = JsonConvert.DeserializeObject<List<Province>>(provinceList);
if (provinces == null)
throw new AppException("Province json is null");
return provinces;
}
}

View File

@ -1,7 +1,10 @@
using MediatR;
using Microsoft.IdentityModel.Tokens;
using NetinaShop.Core.CoreServices.Abstracts;
using NetinaShop.Domain.CommandQueries.Commands;
using NetinaShop.Domain.CommandQueries.Queries;
using NetinaShop.Domain.Enums;
using NetinaShop.Domain.MartenEntities.Settings;
using NetinaShop.Infrastructure.Models.RestApi.Zarinpal;
namespace NetinaShop.Infrastructure.Services;
@ -10,21 +13,29 @@ public class ZarinpalService : IPaymentService
{
private readonly IRestApiWrapper _restApiWrapper;
private readonly IMediator _mediator;
private readonly ISettingService _settingService;
private readonly SiteSettings _siteSettings;
public ZarinpalService(IRestApiWrapper restApiWrapper, IOptionsSnapshot<SiteSettings> snapshot, IMediator mediator)
public ZarinpalService(IRestApiWrapper restApiWrapper, IOptionsSnapshot<SiteSettings> snapshot, IMediator mediator , ISettingService settingService)
{
_restApiWrapper = restApiWrapper;
_mediator = mediator;
_settingService = settingService;
_siteSettings = snapshot.Value;
}
public async Task<string> GetPaymentLinkAsync(double amount, string factorNumber, Guid orderId, Guid userId, string phoneNumber, string fullName, CancellationToken cancellationToken = default)
{
var paymentSetting = (await _settingService.GetSettingAsync("PaymentSetting", cancellationToken)) as PaymentSetting;
if (paymentSetting == null)
throw new AppException("تنظیمات پرداخت انجام نشده است");
if (paymentSetting.ZarinPalApiKey.IsNullOrEmpty())
throw new AppException("کد مرچنت زرین پال وارد نشده است");
var request = new ZarinaplPaymentLinkRequest
{
description = $"پرداخت {amount.ToString("N0")} ریال توسط {fullName} با شماره تماس {phoneNumber} برای سفارش با شماره {factorNumber}",
amount = (int)amount,
callback_url = Path.Combine(_siteSettings.BaseUrl, "api", "accounting", "pay", "verify"),
merchant_id = "4292b845-b510-4d1d-8ee2-097499b198e5",
merchant_id = paymentSetting.ZarinPalApiKey,
metadata = new ZarinaplPaymentLinkRequestMetadata { mobile = phoneNumber }
};
var response = await _restApiWrapper.ZarinpalRestApi.GetPaymentLinkAsync(request);
@ -42,12 +53,18 @@ public class ZarinpalService : IPaymentService
public async Task<Tuple<string, string>> VerifyPaymentAsync(string authority, CancellationToken cancellationToken = default)
{
var paymentSetting = (await _settingService.GetSettingAsync("PaymentSetting", cancellationToken)) as PaymentSetting;
if (paymentSetting == null)
throw new AppException("تنظیمات پرداخت انجام نشده است");
if (paymentSetting.ZarinPalApiKey.IsNullOrEmpty())
throw new AppException("کد مرچنت زرین پال وارد نشده است");
var payment = await _mediator.Send(new GetPaymentQuery(Authority: authority), cancellationToken);
var request = new ZarinaplVerifyPaymentRequest
{
amount = (int)payment.Amount,
authority = payment.Authority,
merchant_id = "4292b845-b510-4d1d-8ee2-097499b198e5"
merchant_id = paymentSetting.ZarinPalApiKey
};
var response = await _restApiWrapper.ZarinpalRestApi.VerifyPaymentAsync(request);
if (response.data.code != 100)