feat : add version 0.19.22.38 , fix zarinpall issue
parent
caf1bdd904
commit
5858cd3236
|
@ -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());
|
||||||
|
}
|
|
@ -16,7 +16,6 @@ if (builder.Environment.IsProduction())
|
||||||
var configuration = builder.Configuration;
|
var configuration = builder.Configuration;
|
||||||
var siteSetting = configuration.GetSection(nameof(SiteSettings)).Get<SiteSettings>();
|
var siteSetting = configuration.GetSection(nameof(SiteSettings)).Get<SiteSettings>();
|
||||||
builder.Services.Configure<SiteSettings>(configuration.GetSection(nameof(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
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
|
@ -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();
|
||||||
|
}
|
|
@ -4,13 +4,11 @@ public class CalculateOrderCommandHandler : IRequestHandler<CalculateOrderComman
|
||||||
{
|
{
|
||||||
private readonly IRepositoryWrapper _repositoryWrapper;
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
private readonly IMediator _mediator;
|
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;
|
_repositoryWrapper = repositoryWrapper;
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
_shopSettings = snapshot.Value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Order> Handle(CalculateOrderCommand request, CancellationToken cancellationToken)
|
public async Task<Order> Handle(CalculateOrderCommand request, CancellationToken cancellationToken)
|
||||||
|
|
|
@ -5,4 +5,5 @@ public class PaymentSetting
|
||||||
public string ZarinPalApiKey { get; set; } = string.Empty;
|
public string ZarinPalApiKey { get; set; } = string.Empty;
|
||||||
public string PayPalApiKey { get; set; } = string.Empty;
|
public string PayPalApiKey { get; set; } = string.Empty;
|
||||||
public string BehPardakhtApiKey { get; set; } = string.Empty;
|
public string BehPardakhtApiKey { get; set; } = string.Empty;
|
||||||
|
public string Shaba { get; set; } = string.Empty;
|
||||||
}
|
}
|
|
@ -6,9 +6,15 @@ public class ShopSetting
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public string Slogan { get; set; } = string.Empty;
|
public string Slogan { get; set; } = string.Empty;
|
||||||
public string City { get; set; } = string.Empty;
|
public string City { get; set; } = string.Empty;
|
||||||
|
public int CityId { get; set; }
|
||||||
public string Province { get; set; } = string.Empty;
|
public string Province { get; set; } = string.Empty;
|
||||||
|
public int ProvinceId { get; set; }
|
||||||
public double LocationLat { get; set; }
|
public double LocationLat { get; set; }
|
||||||
public double LocationLon { get; set; }
|
public double LocationLon { get; set; }
|
||||||
|
public string ENamad { get; set; } = string.Empty;
|
||||||
public string Address { 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; }
|
||||||
}
|
}
|
|
@ -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; }
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,11 +1,5 @@
|
||||||
namespace NetinaShop.Domain.Models.Settings;
|
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 class SiteSettings
|
||||||
{
|
{
|
||||||
public JwtSettings JwtSettings { get; set; } = new JwtSettings();
|
public JwtSettings JwtSettings { get; set; } = new JwtSettings();
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<Folder Include="Dtos\FilterDtos\" />
|
<Folder Include="Dtos\FilterDtos\" />
|
||||||
<Folder Include="Dtos\DashboardDtos\" />
|
<Folder Include="Dtos\DashboardDtos\" />
|
||||||
<Folder Include="Entities\StorageFiles\" />
|
<Folder Include="Entities\StorageFiles\" />
|
||||||
|
<Folder Include="Models\Districts\" />
|
||||||
<Folder Include="Models\Settings\" />
|
<Folder Include="Models\Settings\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
public static class DirectoryAddress
|
public static class DirectoryAddress
|
||||||
{
|
{
|
||||||
private static string _baseDire = $"{Directory.GetCurrentDirectory()}/wwwroot";
|
private static string _baseDire = $"{Directory.GetCurrentDirectory()}/wwwroot";
|
||||||
|
public static string BaseDire = _baseDire ;
|
||||||
public static string Logs = $"{_baseDire}/logs";
|
public static string Logs = $"{_baseDire}/logs";
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using NetinaShop.Core.CoreServices.Abstracts;
|
||||||
using NetinaShop.Domain.CommandQueries.Commands;
|
using NetinaShop.Domain.CommandQueries.Commands;
|
||||||
using NetinaShop.Domain.CommandQueries.Queries;
|
using NetinaShop.Domain.CommandQueries.Queries;
|
||||||
using NetinaShop.Domain.Enums;
|
using NetinaShop.Domain.Enums;
|
||||||
|
using NetinaShop.Domain.MartenEntities.Settings;
|
||||||
using NetinaShop.Infrastructure.Models.RestApi.Zarinpal;
|
using NetinaShop.Infrastructure.Models.RestApi.Zarinpal;
|
||||||
|
|
||||||
namespace NetinaShop.Infrastructure.Services;
|
namespace NetinaShop.Infrastructure.Services;
|
||||||
|
@ -10,21 +13,29 @@ public class ZarinpalService : IPaymentService
|
||||||
{
|
{
|
||||||
private readonly IRestApiWrapper _restApiWrapper;
|
private readonly IRestApiWrapper _restApiWrapper;
|
||||||
private readonly IMediator _mediator;
|
private readonly IMediator _mediator;
|
||||||
|
private readonly ISettingService _settingService;
|
||||||
private readonly SiteSettings _siteSettings;
|
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;
|
_restApiWrapper = restApiWrapper;
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
|
_settingService = settingService;
|
||||||
_siteSettings = snapshot.Value;
|
_siteSettings = snapshot.Value;
|
||||||
}
|
}
|
||||||
public async Task<string> GetPaymentLinkAsync(double amount, string factorNumber, Guid orderId, Guid userId, string phoneNumber, string fullName, CancellationToken cancellationToken = default)
|
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
|
var request = new ZarinaplPaymentLinkRequest
|
||||||
{
|
{
|
||||||
description = $"پرداخت {amount.ToString("N0")} ریال توسط {fullName} با شماره تماس {phoneNumber} برای سفارش با شماره {factorNumber}",
|
description = $"پرداخت {amount.ToString("N0")} ریال توسط {fullName} با شماره تماس {phoneNumber} برای سفارش با شماره {factorNumber}",
|
||||||
amount = (int)amount,
|
amount = (int)amount,
|
||||||
callback_url = Path.Combine(_siteSettings.BaseUrl, "api", "accounting", "pay", "verify"),
|
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 }
|
metadata = new ZarinaplPaymentLinkRequestMetadata { mobile = phoneNumber }
|
||||||
};
|
};
|
||||||
var response = await _restApiWrapper.ZarinpalRestApi.GetPaymentLinkAsync(request);
|
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)
|
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 payment = await _mediator.Send(new GetPaymentQuery(Authority: authority), cancellationToken);
|
||||||
var request = new ZarinaplVerifyPaymentRequest
|
var request = new ZarinaplVerifyPaymentRequest
|
||||||
{
|
{
|
||||||
amount = (int)payment.Amount,
|
amount = (int)payment.Amount,
|
||||||
authority = payment.Authority,
|
authority = payment.Authority,
|
||||||
merchant_id = "4292b845-b510-4d1d-8ee2-097499b198e5"
|
merchant_id = paymentSetting.ZarinPalApiKey
|
||||||
};
|
};
|
||||||
var response = await _restApiWrapper.ZarinpalRestApi.VerifyPaymentAsync(request);
|
var response = await _restApiWrapper.ZarinpalRestApi.VerifyPaymentAsync(request);
|
||||||
if (response.data.code != 100)
|
if (response.data.code != 100)
|
||||||
|
|
Loading…
Reference in New Issue