diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index f441c7fa..3586eeea 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -22,7 +22,7 @@ steps:
displayName: Use Dotnet
inputs:
packageType: sdk
- version: 8.x
+ version: 9.x
- task: NuGetCommand@2
displayName: 'restoring'
inputs:
diff --git a/src/Parbad.AspNetCore/src/Parbad.AspNetCore.csproj b/src/Parbad.AspNetCore/src/Parbad.AspNetCore.csproj
index b33400c5..187016de 100644
--- a/src/Parbad.AspNetCore/src/Parbad.AspNetCore.csproj
+++ b/src/Parbad.AspNetCore/src/Parbad.AspNetCore.csproj
@@ -3,8 +3,8 @@
Parbad.AspNetCore
Parbad.AspNetCore
- 1.4.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0
+ 1.5.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -20,7 +20,7 @@ For more information see: https://www.nuget.org/packages/Parbad/
parbad aspnetcore Payment Gateway Bank Iran Shetab IranKish Mellat Melli Sadad Parsian Pasargad Saman Asan-Pardakht پرداخت درگاه بانک ایران شتاب ایران-کیش ملت ملی سداد پارسیان پاسارگاد سامان آسان-پرداخت
true
LGPL-3.0-or-later
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
@@ -37,8 +37,8 @@ For more information see: https://www.nuget.org/packages/Parbad/
-
-
+
+
diff --git a/src/Parbad.Gateway/FanAva/src/Parbad.Gateway.FanAva.csproj b/src/Parbad.Gateway/FanAva/src/Parbad.Gateway.FanAva.csproj
index 8c228ea7..57bdc507 100644
--- a/src/Parbad.Gateway/FanAva/src/Parbad.Gateway.FanAva.csproj
+++ b/src/Parbad.Gateway/FanAva/src/Parbad.Gateway.FanAva.csproj
@@ -2,8 +2,8 @@
Parbad.Gateway.FanAva
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
- 1.2.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
+ 1.3.0
latest
Mohammad Mokhtari
Copyright © Sina Soltani 2016
@@ -15,7 +15,7 @@
true
parbad Payment Gateway FanAva پرداخت درگاه بانک فن آوا
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
FanAva Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/FanAva/tests/Parbad.Gateway.FanAva.Tests.csproj b/src/Parbad.Gateway/FanAva/tests/Parbad.Gateway.FanAva.Tests.csproj
index d20dd8c4..c78f7f05 100644
--- a/src/Parbad.Gateway/FanAva/tests/Parbad.Gateway.FanAva.Tests.csproj
+++ b/src/Parbad.Gateway/FanAva/tests/Parbad.Gateway.FanAva.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
false
diff --git a/src/Parbad.Gateway/IdPay/src/Parbad.Gateway.IdPay.csproj b/src/Parbad.Gateway/IdPay/src/Parbad.Gateway.IdPay.csproj
index 01439de0..34fb5c52 100644
--- a/src/Parbad.Gateway/IdPay/src/Parbad.Gateway.IdPay.csproj
+++ b/src/Parbad.Gateway/IdPay/src/Parbad.Gateway.IdPay.csproj
@@ -1,8 +1,8 @@
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
- 1.4.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
+ 1.5.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -14,7 +14,7 @@
true
parbad Payment Gateway Bank Iran Shetab idpay پرداخت درگاه بانک ایران شتاب
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
IDPay.ir Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/IdPay/tests/Parbad.Gateway.IdPay.Tests.csproj b/src/Parbad.Gateway/IdPay/tests/Parbad.Gateway.IdPay.Tests.csproj
index a9a78dd3..45d35399 100644
--- a/src/Parbad.Gateway/IdPay/tests/Parbad.Gateway.IdPay.Tests.csproj
+++ b/src/Parbad.Gateway/IdPay/tests/Parbad.Gateway.IdPay.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
false
diff --git a/src/Parbad.Gateway/IranKish/src/Parbad.Gateway.IranKish.csproj b/src/Parbad.Gateway/IranKish/src/Parbad.Gateway.IranKish.csproj
index 8d0b7a00..1478cc29 100644
--- a/src/Parbad.Gateway/IranKish/src/Parbad.Gateway.IranKish.csproj
+++ b/src/Parbad.Gateway/IranKish/src/Parbad.Gateway.IranKish.csproj
@@ -3,8 +3,8 @@
Parbad.Gateway.IranKish
Parbad.Gateway.IranKish
- 1.1.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.2.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -16,7 +16,7 @@
true
parbad Payment gateway bank Iran shetab irankish پرداخت درگاه بانک ایران کیش
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
IranKish Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/IranKish/tests/Parbad.Gateway.IranKish.Tests.csproj b/src/Parbad.Gateway/IranKish/tests/Parbad.Gateway.IranKish.Tests.csproj
index de39da7c..b8c73ac9 100644
--- a/src/Parbad.Gateway/IranKish/tests/Parbad.Gateway.IranKish.Tests.csproj
+++ b/src/Parbad.Gateway/IranKish/tests/Parbad.Gateway.IranKish.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
enable
enable
diff --git a/src/Parbad.Gateway/PayIr/src/Parbad.Gateway.PayIr.csproj b/src/Parbad.Gateway/PayIr/src/Parbad.Gateway.PayIr.csproj
index 3fbe9a4b..7d14a403 100644
--- a/src/Parbad.Gateway/PayIr/src/Parbad.Gateway.PayIr.csproj
+++ b/src/Parbad.Gateway/PayIr/src/Parbad.Gateway.PayIr.csproj
@@ -3,8 +3,8 @@
Parbad.Gateway.PayIr
Parbad.Gateway.PayIr
- 1.6.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.7.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -16,7 +16,7 @@
true
parbad Payment Gateway Bank Iran Shetab pay.ir پرداخت درگاه بانک ایران شتاب پی
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
Pay.ir Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/PayPing/src/Parbad.Gateway.PayPing.csproj b/src/Parbad.Gateway/PayPing/src/Parbad.Gateway.PayPing.csproj
index 6719961c..3bab81b6 100644
--- a/src/Parbad.Gateway/PayPing/src/Parbad.Gateway.PayPing.csproj
+++ b/src/Parbad.Gateway/PayPing/src/Parbad.Gateway.PayPing.csproj
@@ -2,8 +2,8 @@
Parbad.Gateway.PayPing
Parbad.Gateway.PayPing
- 1.3.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.4.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Ali Zaferany
Copyright © Parbad 2016
@@ -16,7 +16,7 @@
LGPL-3.0-or-later
false
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
PayPing Gateway for Parbad project.
For more information see: https://github.com/Sina-Soltani/Parbad
diff --git a/src/Parbad.Gateway/Sepehr/src/Parbad.Gateway.Sepehr.csproj b/src/Parbad.Gateway/Sepehr/src/Parbad.Gateway.Sepehr.csproj
index 5c2e5921..e4f121d9 100644
--- a/src/Parbad.Gateway/Sepehr/src/Parbad.Gateway.Sepehr.csproj
+++ b/src/Parbad.Gateway/Sepehr/src/Parbad.Gateway.Sepehr.csproj
@@ -3,8 +3,8 @@
Parbad.Gateway.Sepehr
Parbad.Gateway.Sepehr
- 1.5.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.6.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -16,7 +16,7 @@
true
parbad Payment gateway bank Iran shetab sepehr mabna پرداخت درگاه بانک ایران شتاب سپهر مبنا کارت
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
Sepehr Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/YekPay/src/Parbad.Gateway.YekPay.csproj b/src/Parbad.Gateway/YekPay/src/Parbad.Gateway.YekPay.csproj
index 9a41c381..6bb11d81 100644
--- a/src/Parbad.Gateway/YekPay/src/Parbad.Gateway.YekPay.csproj
+++ b/src/Parbad.Gateway/YekPay/src/Parbad.Gateway.YekPay.csproj
@@ -3,8 +3,8 @@
Parbad.Gateway.YekPay
Parbad.Gateway.YekPay
- 1.4.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.5.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -16,7 +16,7 @@
true
parbad Payment gateway bank Iran shetab yekpay پرداخت درگاه بانک ایران شتاب یک پی
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
YekPay Gateway for Parbad project.
For more information see: https://www.nuget.org/packages/Parbad/
diff --git a/src/Parbad.Gateway/ZarinPal/src/Parbad.Gateway.ZarinPal.csproj b/src/Parbad.Gateway/ZarinPal/src/Parbad.Gateway.ZarinPal.csproj
index 10282047..c8591369 100644
--- a/src/Parbad.Gateway/ZarinPal/src/Parbad.Gateway.ZarinPal.csproj
+++ b/src/Parbad.Gateway/ZarinPal/src/Parbad.Gateway.ZarinPal.csproj
@@ -3,8 +3,8 @@
Parbad.Gateway.ZarinPal
Parbad.Gateway.ZarinPal
- 1.5.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net6.0;net7.0;net8
+ 1.6.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net6.0;net7.0;net8;net9.0
latest
Sina Soltani
Copyright © Sina Soltani 2016
@@ -19,7 +19,7 @@
ZarinPal Gateway for Parbad project.
For more information see: https://github.com/Sina-Soltani/Parbad
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
diff --git a/src/Parbad.Gateway/Zibal/src/Parbad.Gateway.Zibal.csproj b/src/Parbad.Gateway/Zibal/src/Parbad.Gateway.Zibal.csproj
index 05cda53b..4f36f226 100644
--- a/src/Parbad.Gateway/Zibal/src/Parbad.Gateway.Zibal.csproj
+++ b/src/Parbad.Gateway/Zibal/src/Parbad.Gateway.Zibal.csproj
@@ -4,8 +4,8 @@
Parbad.Gateway.Zibal
Parbad.Gateway.Zibal
enable
- 1.2.0
- netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0
+ 1.3.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Mohammad Ashrafi
Copyright © Sina Soltani 2016
@@ -17,7 +17,7 @@
true
parbad Payment Gateway Bank Iran Shetab zibal پرداخت درگاه بانک ایران شتاب زیبال
True
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
Zibal Gateway for Parbad project.
For more information see: https://github.com/Sina-Soltani/Parbad
diff --git a/src/Parbad.Shared/DependencyInjectionExtensions.cs b/src/Parbad.Shared/DependencyInjectionExtensions.cs
index 15d78fbf..9aad7c6f 100644
--- a/src/Parbad.Shared/DependencyInjectionExtensions.cs
+++ b/src/Parbad.Shared/DependencyInjectionExtensions.cs
@@ -1,103 +1,102 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
-namespace Microsoft.Extensions.DependencyInjection
+namespace Microsoft.Extensions.DependencyInjection;
+
+internal static class DependencyInjectionExtensions
{
- internal static class DependencyInjectionExtensions
+ public static IServiceCollection Add(this IServiceCollection services, Type serviceType, ServiceLifetime lifetime)
+ {
+ services.Add(ServiceDescriptor.Describe(serviceType, serviceType, lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection Add(this IServiceCollection services, ServiceLifetime lifetime) where TService : class
+ {
+ services.Add(ServiceDescriptor.Describe(typeof(TService), typeof(TService), lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection Add(this IServiceCollection services, ServiceLifetime lifetime)
+ where TService : class
+ where TImplementation : class, TService
+ {
+ services.Add(ServiceDescriptor.Describe(typeof(TService), typeof(TImplementation), lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection Add(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
+ where TService : class
+ {
+ services.Add(ServiceDescriptor.Describe(typeof(TService), factory, lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection TryAdd(this IServiceCollection services, Type serviceType, ServiceLifetime lifetime)
+ {
+ services.TryAdd(ServiceDescriptor.Describe(serviceType, serviceType, lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection TryAdd(this IServiceCollection services, ServiceLifetime lifetime) where TService : class
+ {
+ services.TryAdd(ServiceDescriptor.Describe(typeof(TService), typeof(TService), lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection TryAdd(this IServiceCollection services, ServiceLifetime lifetime)
+ where TService : class
+ where TImplementation : class, TService
+ {
+ services.TryAdd(ServiceDescriptor.Describe(typeof(TService), typeof(TImplementation), lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection TryAdd(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
+ where TService : class
+ {
+ services.TryAdd(ServiceDescriptor.Describe(typeof(TService), factory, lifetime));
+
+ return services;
+ }
+
+ public static IServiceCollection AddOrUpdate(this IServiceCollection services, ServiceLifetime lifetime)
+ where TService : class
+ {
+ return services
+ .RemoveAll()
+ .Add(lifetime);
+ }
+
+ public static IServiceCollection AddOrUpdate(this IServiceCollection services, ServiceLifetime lifetime)
+ where TService : class
+ where TImplementation : class, TService
+ {
+ return services
+ .RemoveAll()
+ .Add(lifetime);
+ }
+
+ public static IServiceCollection AddOrUpdate(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
+ where TService : class
+ {
+ return services
+ .RemoveAll()
+ .Add(factory, lifetime);
+ }
+
+ public static IServiceCollection AddOrUpdate(this IServiceCollection services, TService implementationInstance)
+ where TService : class
{
- public static IServiceCollection Add(this IServiceCollection services, Type serviceType, ServiceLifetime lifetime)
- {
- services.Add(ServiceDescriptor.Describe(serviceType, serviceType, lifetime));
-
- return services;
- }
-
- public static IServiceCollection Add(this IServiceCollection services, ServiceLifetime lifetime) where TService : class
- {
- services.Add(ServiceDescriptor.Describe(typeof(TService), typeof(TService), lifetime));
-
- return services;
- }
-
- public static IServiceCollection Add(this IServiceCollection services, ServiceLifetime lifetime)
- where TService : class
- where TImplementation : class, TService
- {
- services.Add(ServiceDescriptor.Describe(typeof(TService), typeof(TImplementation), lifetime));
-
- return services;
- }
-
- public static IServiceCollection Add(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
- where TService : class
- {
- services.Add(ServiceDescriptor.Describe(typeof(TService), factory, lifetime));
-
- return services;
- }
-
- public static IServiceCollection TryAdd(this IServiceCollection services, Type serviceType, ServiceLifetime lifetime)
- {
- services.TryAdd(ServiceDescriptor.Describe(serviceType, serviceType, lifetime));
-
- return services;
- }
-
- public static IServiceCollection TryAdd(this IServiceCollection services, ServiceLifetime lifetime) where TService : class
- {
- services.TryAdd(ServiceDescriptor.Describe(typeof(TService), typeof(TService), lifetime));
-
- return services;
- }
-
- public static IServiceCollection TryAdd(this IServiceCollection services, ServiceLifetime lifetime)
- where TService : class
- where TImplementation : class, TService
- {
- services.TryAdd(ServiceDescriptor.Describe(typeof(TService), typeof(TImplementation), lifetime));
-
- return services;
- }
-
- public static IServiceCollection TryAdd(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
- where TService : class
- {
- services.TryAdd(ServiceDescriptor.Describe(typeof(TService), factory, lifetime));
-
- return services;
- }
-
- public static IServiceCollection AddOrUpdate(this IServiceCollection services, ServiceLifetime lifetime)
- where TService : class
- {
- return services
- .RemoveAll()
- .Add(lifetime);
- }
-
- public static IServiceCollection AddOrUpdate(this IServiceCollection services, ServiceLifetime lifetime)
- where TService : class
- where TImplementation : class, TService
- {
- return services
- .RemoveAll()
- .Add(lifetime);
- }
-
- public static IServiceCollection AddOrUpdate(this IServiceCollection services, Func factory, ServiceLifetime lifetime)
- where TService : class
- {
- return services
- .RemoveAll()
- .Add(factory, lifetime);
- }
-
- public static IServiceCollection AddOrUpdate(this IServiceCollection services, TService implementationInstance)
- where TService : class
- {
- return services
- .RemoveAll()
- .AddSingleton(implementationInstance);
- }
+ return services
+ .RemoveAll()
+ .AddSingleton(implementationInstance);
}
}
diff --git a/src/Parbad.Storage/Abstractions/IStorage.cs b/src/Parbad.Storage/Abstractions/IStorage.cs
index d1d9434a..ca8f8545 100644
--- a/src/Parbad.Storage/Abstractions/IStorage.cs
+++ b/src/Parbad.Storage/Abstractions/IStorage.cs
@@ -1,8 +1,10 @@
// Copyright (c) Parbad. All rights reserved.
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
-using Parbad.Storage.Abstractions.Models;
+using System;
+using System.Collections.Generic;
using System.Linq;
+using Parbad.Storage.Abstractions.Models;
using System.Threading;
using System.Threading.Tasks;
@@ -16,11 +18,13 @@ public interface IStorage
///
/// Gets a list of .
///
+ [Obsolete("This property will be removed in a future release. The usages are implemented as methods now.")]
IQueryable Payments { get; }
///
/// Gets a list of .
///
+ [Obsolete("This property will be removed in a future release. The usages are implemented as methods now.")]
IQueryable Transactions { get; }
///
@@ -64,4 +68,39 @@ public interface IStorage
///
///
Task DeleteTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets a payment by its tracking number.
+ ///
+ ///
+ ///
+ Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets a payment by its token.
+ ///
+ ///
+ ///
+ Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default);
+
+ ///
+ /// Checks whether a payment exists with the given .
+ ///
+ ///
+ ///
+ Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default);
+
+ ///
+ /// Checks whether a payment exists with the given .
+ ///
+ ///
+ ///
+ Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets a list of transactions of the given .
+ ///
+ ///
+ ///
+ Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default);
}
diff --git a/src/Parbad.Storage/Abstractions/IStorageManager.cs b/src/Parbad.Storage/Abstractions/IStorageManager.cs
index e1058f57..2a91753a 100644
--- a/src/Parbad.Storage/Abstractions/IStorageManager.cs
+++ b/src/Parbad.Storage/Abstractions/IStorageManager.cs
@@ -1,71 +1,12 @@
// Copyright (c) Parbad. All rights reserved.
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
-using Parbad.Storage.Abstractions.Models;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
+using System;
namespace Parbad.Storage.Abstractions;
///
-/// Provides the APIs for managing payment and transaction in a persistence store.
+/// Provides the APIs for managing payments and transactions in a persistence store.
///
-public interface IStorageManager
-{
- ///
- /// Creates a new payment.
- ///
- ///
- ///
- Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default);
-
- ///
- /// Updates the given .
- ///
- ///
- ///
- Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default);
-
- ///
- /// Creates a new transaction.
- ///
- ///
- ///
- Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default);
-
- ///
- /// Gets a payment by its tracking number.
- ///
- ///
- ///
- Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default);
-
- ///
- /// Gets a payment by its token.
- ///
- ///
- ///
- Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default);
-
- ///
- /// Checks whether a payment exists with the given .
- ///
- ///
- ///
- Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default);
-
- ///
- /// Checks whether a payment exists with the given .
- ///
- ///
- ///
- Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default);
-
- ///
- /// Gets a list of transactions of the given .
- ///
- ///
- ///
- Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default);
-}
+[Obsolete("This interface will be removed in a future release. All methods are moved to IStorage interface.")]
+public interface IStorageManager : IStorage;
diff --git a/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.csproj b/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.csproj
index 29fbeaa7..98e02b90 100644
--- a/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.csproj
+++ b/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.csproj
@@ -3,9 +3,10 @@
Parbad.Storage.Abstractions
Parbad.Storage.Abstractions
- 1.2.0
+ 1.3.0
latest
- netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0
+ enable
false
true
LGPL-3.0-or-later
@@ -19,7 +20,7 @@ More information: https://github.com/Sina-Soltani/Parbad
parbad storage
true
Sina Soltani
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
@@ -37,7 +38,7 @@ More information: https://github.com/Sina-Soltani/Parbad
-
+
diff --git a/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.xml b/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.xml
index 11a720fd..b2fb827d 100644
--- a/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.xml
+++ b/src/Parbad.Storage/Abstractions/Parbad.Storage.Abstractions.xml
@@ -61,96 +61,75 @@
-
-
- A builder for building the Parbad storage.
-
-
-
-
- Specifies the contract for a collection of service descriptors.
-
-
-
-
- Adds the given storage to Parbad services.
-
-
- Lifetime of the given storage.
-
-
+
- Adds the given storage to Parbad services as singleton.
+ Gets a payment by its tracking number.
-
+
+
-
+
- Adds the given storage to Parbad services.
+ Gets a payment by its token.
-
- Lifetime of the given storage.
+
+
-
+
- Provides the APIs for managing payment and transaction in a persistence store.
+ Checks whether a payment exists with the given .
+
+
-
+
- Creates a new payment.
+ Checks whether a payment exists with the given .
-
+
-
+
- Updates the given .
+ Gets a list of transactions of the given .
-
+
- Creates a new transaction.
+ A builder for building the Parbad storage.
-
-
-
+
- Gets a payment by its tracking number.
+ Specifies the contract for a collection of service descriptors.
-
-
-
+
- Gets a payment by its token.
+ Adds the given storage to Parbad services.
-
-
+
+ Lifetime of the given storage.
-
+
- Checks whether a payment exists with the given .
+ Adds the given storage to Parbad services as singleton.
-
-
+
-
+
- Checks whether a payment exists with the given .
+ Adds the given storage to Parbad services.
-
-
+
+ Lifetime of the given storage.
-
+
- Gets a list of transactions of the given .
+ Provides the APIs for managing payments and transactions in a persistence store.
-
-
@@ -190,5 +169,20 @@
The lifetime of given StorageManager.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Parbad.Storage/Abstractions/StorageBuilderExtensions.cs b/src/Parbad.Storage/Abstractions/StorageBuilderExtensions.cs
index f751e191..6906d29e 100644
--- a/src/Parbad.Storage/Abstractions/StorageBuilderExtensions.cs
+++ b/src/Parbad.Storage/Abstractions/StorageBuilderExtensions.cs
@@ -12,6 +12,7 @@ public static class StorageBuilderExtensions
///
///
/// The lifetime of given StorageManager.
+ [Obsolete("StorageManager will be removed in a future release. The implementations are moved to the IStorage interface.")]
public static IStorageBuilder AddStorageManager(this IStorageBuilder builder, ServiceLifetime lifetime) where TManager : class, IStorageManager
{
builder.Services.AddOrUpdate(lifetime);
@@ -24,6 +25,7 @@ public static IStorageBuilder AddStorageManager(this IStorageBuilder b
///
///
///
+ [Obsolete("StorageManager will be removed in a future release. The implementations are moved to the IStorage interface.")]
public static IStorageBuilder AddStorageManager(this IStorageBuilder builder, IStorageManager storageManager)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
@@ -42,6 +44,7 @@ public static IStorageBuilder AddStorageManager(this IStorageBuilder builder, IS
///
///
/// The lifetime of given StorageManager.
+ [Obsolete("StorageManager will be removed in a future release. The implementations are moved to the IStorage interface.")]
public static IStorageBuilder AddStorageManager(this IStorageBuilder builder, Func factory, ServiceLifetime lifetime)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
diff --git a/src/Parbad.Storage/Abstractions/StorageExtensions.cs b/src/Parbad.Storage/Abstractions/StorageExtensions.cs
new file mode 100644
index 00000000..5331c5a9
--- /dev/null
+++ b/src/Parbad.Storage/Abstractions/StorageExtensions.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Parbad.Storage.Abstractions.Models;
+
+namespace Parbad.Storage.Abstractions;
+
+public static class StorageExtensions
+{
+ ///
+ public static Task GetPaymentByTrackingNumberAsync(this IStorage storage,
+ long trackingNumber,
+ CancellationToken cancellationToken = default)
+ {
+ if (storage == null) throw new ArgumentNullException(nameof(storage));
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ return Task.FromResult(storage.Payments.SingleOrDefault(model => model.TrackingNumber == trackingNumber));
+ }
+
+ ///
+ public static Task GetPaymentByTokenAsync(this IStorage storage,
+ string paymentToken,
+ CancellationToken cancellationToken = default)
+ {
+ if (storage == null) throw new ArgumentNullException(nameof(storage));
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ return Task.FromResult(storage.Payments.SingleOrDefault(model => model.Token == paymentToken));
+ }
+
+ ///
+ public static Task DoesPaymentExistAsync(this IStorage storage,
+ long trackingNumber,
+ CancellationToken cancellationToken = default)
+ {
+ if (storage == null) throw new ArgumentNullException(nameof(storage));
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ return Task.FromResult(storage.Payments.Any(model => model.TrackingNumber == trackingNumber));
+ }
+
+ ///
+ public static Task DoesPaymentExistAsync(this IStorage storage,
+ string paymentToken,
+ CancellationToken cancellationToken = default)
+ {
+ if (storage == null) throw new ArgumentNullException(nameof(storage));
+
+ return Task.FromResult(storage.Payments.Any(model => model.Token == paymentToken));
+ }
+
+ ///
+ public static Task> GetTransactionsAsync(this IStorage storage,
+ Payment payment,
+ CancellationToken cancellationToken = default)
+ {
+ if (storage == null) throw new ArgumentNullException(nameof(storage));
+
+ return Task.FromResult(storage.Transactions.Where(model => model.PaymentId == payment.Id).ToList());
+ }
+}
diff --git a/src/Parbad.Storage/Cache/src/Abstractions/CacheStorage.cs b/src/Parbad.Storage/Cache/src/Abstractions/CacheStorage.cs
index a9ffe426..66d355a5 100644
--- a/src/Parbad.Storage/Cache/src/Abstractions/CacheStorage.cs
+++ b/src/Parbad.Storage/Cache/src/Abstractions/CacheStorage.cs
@@ -4,6 +4,7 @@
using Parbad.Storage.Abstractions;
using Parbad.Storage.Abstractions.Models;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -35,6 +36,7 @@ public virtual Task CreatePaymentAsync(Payment payment, CancellationToken cancel
payment.Id = GenerateNewPaymentId();
var record = FindPayment(payment);
+
if (record != null) throw new InvalidOperationException($"There is already a payment record in database with id {payment.Id}");
Collection.Payments.Add(payment);
@@ -85,6 +87,7 @@ public virtual Task CreateTransactionAsync(Transaction transaction, Cancellation
transaction.Id = GenerateNewTransactionId();
var record = FindTransaction(transaction);
+
if (record != null) throw new InvalidOperationException($"There is already a transaction record in database with id {transaction.Id}");
Collection.Transactions.Add(transaction);
@@ -122,11 +125,61 @@ public virtual Task DeleteTransactionAsync(Transaction transaction, Cancellation
return SaveChangesAsync(cancellationToken);
}
+ ///
+ public virtual Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var record = Collection.Payments.SingleOrDefault(payment => payment.TrackingNumber == trackingNumber);
+
+ return Task.FromResult(record);
+ }
+
+ ///
+ public virtual Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var record = Collection.Payments.SingleOrDefault(payment => payment.Token == paymentToken);
+
+ return Task.FromResult(record);
+ }
+
+ ///
+ public virtual Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var exists = Collection.Payments.Any(payment => payment.TrackingNumber == trackingNumber);
+
+ return Task.FromResult(exists);
+ }
+
+ ///
+ public virtual Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var exists = Collection.Payments.Any(payment => payment.Token == paymentToken);
+
+ return Task.FromResult(exists);
+ }
+
+ ///
+ public virtual Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default)
+ {
+ var transactions = Collection.Transactions
+ .Where(transaction => transaction.PaymentId == payment.Id)
+ .ToList();
+
+ return Task.FromResult(transactions);
+ }
+
///
/// Finds a payment in storage.
///
///
- protected virtual Payment FindPayment(Payment payment)
+ protected virtual Payment? FindPayment(Payment payment)
{
return Collection.Payments.Contains(payment)
? payment
@@ -137,7 +190,7 @@ protected virtual Payment FindPayment(Payment payment)
/// Finds a transaction in storage.
///
///
- protected virtual Transaction FindTransaction(Transaction transaction)
+ protected virtual Transaction? FindTransaction(Transaction transaction)
{
return Collection.Transactions.Contains(transaction)
? transaction
diff --git a/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.csproj b/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.csproj
index d7d418f2..bc851005 100644
--- a/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.csproj
+++ b/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.csproj
@@ -2,9 +2,10 @@
Parbad.Storage.Cache
- 1.4.0
+ 1.5.0
latest
- netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0
+ enable
false
true
LGPL-3.0-or-later
@@ -19,7 +20,7 @@ More information: https://github.com/Sina-Soltani/Parbad
true
Sina Soltani
Parbad.Storage.Cache
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
@@ -41,7 +42,7 @@ More information: https://github.com/Sina-Soltani/Parbad
-
+
diff --git a/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.xml b/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.xml
index 8f347608..70af4a4f 100644
--- a/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.xml
+++ b/src/Parbad.Storage/Cache/src/Parbad.Storage.Cache.xml
@@ -38,6 +38,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Finds a payment in storage.
diff --git a/src/Parbad.Storage/Cache/tests/Parbad.Storage.Cache.Tests.csproj b/src/Parbad.Storage/Cache/tests/Parbad.Storage.Cache.Tests.csproj
index f87da84a..ae661946 100644
--- a/src/Parbad.Storage/Cache/tests/Parbad.Storage.Cache.Tests.csproj
+++ b/src/Parbad.Storage/Cache/tests/Parbad.Storage.Cache.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
false
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Builder/EntityFrameworkStorageBuilderExtensions.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Builder/EntityFrameworkStorageBuilderExtensions.cs
index 7e284355..517c51b7 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Builder/EntityFrameworkStorageBuilderExtensions.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Builder/EntityFrameworkStorageBuilderExtensions.cs
@@ -7,44 +7,40 @@
using Parbad.Storage.EntityFrameworkCore.Options;
using System;
-namespace Parbad.Storage.EntityFrameworkCore.Builder
+namespace Parbad.Storage.EntityFrameworkCore.Builder;
+
+public static class EntityFrameworkStorageBuilderExtensions
{
- public static class EntityFrameworkStorageBuilderExtensions
+ ///
+ /// Uses the EntityFramework Core as a storage for saving and loading data.
+ ///
+ /// Note: It means Parbad can save and load the data in different database providers
+ /// such as SQL Server, MySql, Sqlite, PostgreSQL, Oracle, InMemory, etc.
+ /// For more information see: https://docs.microsoft.com/en-us/ef/core/providers/.
+ ///
+ /// Note: This database is only for internal usages such as saving and loading payment information.
+ /// You don't need to think about merging and using this database with your own database.
+ /// The important payment information such as Tracking Number, Transaction Code, etc. will you get from the result of
+ /// all payment requests.
+ ///
+ ///
+ /// Configures the EntityFrameworkCore options for Parbad.
+ public static IStorageBuilder UseEfCore(this IStorageBuilder builder, Action configureEfCoreOptions)
{
- ///
- /// Uses the EntityFramework Core as a storage for saving and loading data.
- ///
- /// Note: It means Parbad can save and load the data in different database providers
- /// such as SQL Server, MySql, Sqlite, PostgreSQL, Oracle, InMemory, etc.
- /// For more information see: https://docs.microsoft.com/en-us/ef/core/providers/.
- ///
- /// Note: This database is only for internal usages such as saving and loading payment information.
- /// You don't need to think about merging and using this database with your own database.
- /// The important payment information such as Tracking Number, Transaction Code, etc. will you get from the result of
- /// all payment requests.
- ///
- ///
- /// Configures the EntityFrameworkCore options for Parbad.
- public static IStorageBuilder UseEfCore(this IStorageBuilder builder, Action configureEfCoreOptions)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (configureEfCoreOptions == null) throw new ArgumentNullException(nameof(configureEfCoreOptions));
-
- var options = new EntityFrameworkCoreOptions();
- configureEfCoreOptions(options);
-
- builder.Services.Configure(configureEfCoreOptions);
-
- builder.Services.AddDbContext(dbBuilder =>
- {
- options.ConfigureDbContext?.Invoke(dbBuilder);
- });
-
- builder.AddStorage(ServiceLifetime.Transient);
-
- builder.AddStorageManager(ServiceLifetime.Transient);
-
- return builder;
- }
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (configureEfCoreOptions == null) throw new ArgumentNullException(nameof(configureEfCoreOptions));
+
+ var options = new EntityFrameworkCoreOptions();
+ configureEfCoreOptions(options);
+
+ builder.Services.Configure(configureEfCoreOptions);
+
+ builder.Services.AddDbContext(dbBuilder => options.ConfigureDbContext?.Invoke(dbBuilder));
+
+ builder.AddStorage(ServiceLifetime.Transient);
+
+ builder.AddStorageManager(ServiceLifetime.Transient);
+
+ return builder;
}
}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfiguration.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfiguration.cs
index e84d1c0f..9b5b48f5 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfiguration.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfiguration.cs
@@ -5,36 +5,35 @@
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Parbad.Storage.EntityFrameworkCore.Options;
-namespace Parbad.Storage.EntityFrameworkCore.Configuration
+namespace Parbad.Storage.EntityFrameworkCore.Configuration;
+
+///
+/// Applies the configuration on the specified entity.
+///
+///
+public abstract class EntityTypeConfiguration : IEntityTypeConfiguration where TEntity : class
{
///
- /// Applies the configuration on the specified entity.
+ /// Initializes an instance of .
///
- ///
- public abstract class EntityTypeConfiguration : IEntityTypeConfiguration where TEntity : class
+ protected EntityTypeConfiguration(EntityFrameworkCoreOptions efCoreOptions)
{
- ///
- /// Initializes an instance of .
- ///
- protected EntityTypeConfiguration(EntityFrameworkCoreOptions efCoreOptions)
- {
- EntityFrameworkCoreOptions = efCoreOptions;
- }
-
- ///
- /// Contains the options for configuring the EntityFrameworkCore for Parbad storage.
- ///
- public EntityFrameworkCoreOptions EntityFrameworkCoreOptions { get; }
+ EntityFrameworkCoreOptions = efCoreOptions;
+ }
- ///
- public void Configure(EntityTypeBuilder builder)
- {
- Configure(builder, EntityFrameworkCoreOptions);
- }
+ ///
+ /// Contains the options for configuring the EntityFrameworkCore for Parbad storage.
+ ///
+ public EntityFrameworkCoreOptions EntityFrameworkCoreOptions { get; }
- ///
- /// Configures the entity.
- ///
- public abstract void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions tableOptions);
+ ///
+ public void Configure(EntityTypeBuilder builder)
+ {
+ Configure(builder, EntityFrameworkCoreOptions);
}
-}
+
+ ///
+ /// Configures the entity.
+ ///
+ public abstract void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions tableOptions);
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfigurationExtensions.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfigurationExtensions.cs
index 68bfacf9..7207e71b 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfigurationExtensions.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/EntityTypeConfigurationExtensions.cs
@@ -6,31 +6,30 @@
using Parbad.Storage.EntityFrameworkCore.Options;
using System;
-namespace Parbad.Storage.EntityFrameworkCore.Configuration
+namespace Parbad.Storage.EntityFrameworkCore.Configuration;
+
+internal static class EntityTypeConfigurationExtensions
{
- internal static class EntityTypeConfigurationExtensions
+ public static EntityTypeBuilder ToTable(this EntityTypeBuilder entityTypeBuilder, TableOptions options, string defaultSchema)
{
- public static EntityTypeBuilder ToTable(this EntityTypeBuilder entityTypeBuilder, TableOptions options, string defaultSchema)
- {
- if (options == null) throw new ArgumentNullException(nameof(options));
-
- var schema = string.IsNullOrWhiteSpace(options.Schema) ? defaultSchema : options.Schema;
+ if (options == null) throw new ArgumentNullException(nameof(options));
- if (string.IsNullOrWhiteSpace(options.Name))
- {
- throw new Exception("Table name cannot be null or empty.");
- }
+ var schema = string.IsNullOrWhiteSpace(options.Schema) ? defaultSchema : options.Schema;
- if (string.IsNullOrWhiteSpace(schema))
- {
- entityTypeBuilder.ToTable(options.Name);
- }
- else
- {
- entityTypeBuilder.ToTable(options.Name, schema);
- }
+ if (string.IsNullOrWhiteSpace(options.Name))
+ {
+ throw new Exception("Table name cannot be null or empty.");
+ }
- return entityTypeBuilder;
+ if (string.IsNullOrWhiteSpace(schema))
+ {
+ entityTypeBuilder.ToTable(options.Name);
+ }
+ else
+ {
+ entityTypeBuilder.ToTable(options.Name, schema);
}
+
+ return entityTypeBuilder;
}
-}
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/PaymentConfiguration.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/PaymentConfiguration.cs
index c9031cff..cff177f8 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/PaymentConfiguration.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/PaymentConfiguration.cs
@@ -6,81 +6,80 @@
using Parbad.Storage.EntityFrameworkCore.Domain;
using Parbad.Storage.EntityFrameworkCore.Options;
-namespace Parbad.Storage.EntityFrameworkCore.Configuration
+namespace Parbad.Storage.EntityFrameworkCore.Configuration;
+
+///
+/// Payment entity configuration.
+///
+public class PaymentConfiguration : EntityTypeConfiguration
{
///
- /// Payment entity configuration.
+ /// Initializes an instance of .
///
- public class PaymentConfiguration : EntityTypeConfiguration
+ public PaymentConfiguration(EntityFrameworkCoreOptions efCoreOptions) : base(efCoreOptions)
+ {
+ }
+
+ ///
+ public override void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions efCoreOptions)
{
- ///
- /// Initializes an instance of .
- ///
- public PaymentConfiguration(EntityFrameworkCoreOptions efCoreOptions) : base(efCoreOptions)
- {
- }
-
- ///
- public override void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions efCoreOptions)
- {
- builder.ToTable(efCoreOptions.PaymentTableOptions, efCoreOptions.DefaultSchema);
-
- builder
- .HasKey(entity => entity.Id)
- .HasName("payment_id");
- builder.Property(entity => entity.Id)
- .HasColumnName("payment_id")
- .ValueGeneratedOnAdd();
-
- builder.Property(entity => entity.TrackingNumber)
- .HasColumnName("tracking_number")
- .IsRequired(required: true);
- builder.HasIndex(entity => entity.TrackingNumber).IsUnique(unique: true);
-
- builder.Property(entity => entity.Token)
- .HasColumnName(nameof(PaymentEntity.Token).ToLower())
- .IsRequired(required: true);
- builder.HasIndex(entity => entity.Token).IsUnique(unique: true);
-
- builder.Property(entity => entity.Amount)
- .HasColumnName(nameof(PaymentEntity.Amount).ToLower())
- .HasColumnType("decimal(18,2)")
- .IsRequired(required: true);
-
- builder.Property(entity => entity.TransactionCode)
- .HasColumnName("transaction_code")
- .IsRequired(required: false);
-
- builder.Property(entity => entity.GatewayName)
- .HasColumnName("gateway_name")
- .HasMaxLength(20)
- .IsRequired(required: true);
-
- builder.Property(entity => entity.IsCompleted)
- .HasColumnName("is_completed")
- .IsRequired(required: true);
-
- builder.Property(entity => entity.IsPaid)
- .HasColumnName("is_paid")
- .IsRequired(required: true);
-
- builder.Property(entity => entity.GatewayAccountName)
- .HasColumnName("gateway_account_name")
- .IsRequired(required: false);
-
- builder.Property(entity => entity.CreatedOn)
- .HasColumnName("created_on")
- .IsRequired(required: true);
-
- builder.Property(entity => entity.UpdatedOn)
- .HasColumnName("updated_on")
- .IsRequired(required: false);
-
- builder
- .HasMany(entity => entity.Transactions)
- .WithOne(entity => entity.Payment)
- .HasForeignKey(entity => entity.PaymentId)
- .OnDelete(DeleteBehavior.Cascade);
- }
+ builder.ToTable(efCoreOptions.PaymentTableOptions, efCoreOptions.DefaultSchema);
+
+ builder
+ .HasKey(entity => entity.Id)
+ .HasName("payment_id");
+ builder.Property(entity => entity.Id)
+ .HasColumnName("payment_id")
+ .ValueGeneratedOnAdd();
+
+ builder.Property(entity => entity.TrackingNumber)
+ .HasColumnName("tracking_number")
+ .IsRequired(required: true);
+ builder.HasIndex(entity => entity.TrackingNumber).IsUnique(unique: true);
+
+ builder.Property(entity => entity.Token)
+ .HasColumnName(nameof(PaymentEntity.Token).ToLower())
+ .IsRequired(required: true);
+ builder.HasIndex(entity => entity.Token).IsUnique(unique: true);
+
+ builder.Property(entity => entity.Amount)
+ .HasColumnName(nameof(PaymentEntity.Amount).ToLower())
+ .HasColumnType("decimal(18,2)")
+ .IsRequired(required: true);
+
+ builder.Property(entity => entity.TransactionCode)
+ .HasColumnName("transaction_code")
+ .IsRequired(required: false);
+
+ builder.Property(entity => entity.GatewayName)
+ .HasColumnName("gateway_name")
+ .HasMaxLength(20)
+ .IsRequired(required: true);
+
+ builder.Property(entity => entity.IsCompleted)
+ .HasColumnName("is_completed")
+ .IsRequired(required: true);
+
+ builder.Property(entity => entity.IsPaid)
+ .HasColumnName("is_paid")
+ .IsRequired(required: true);
+
+ builder.Property(entity => entity.GatewayAccountName)
+ .HasColumnName("gateway_account_name")
+ .IsRequired(required: false);
+
+ builder.Property(entity => entity.CreatedOn)
+ .HasColumnName("created_on")
+ .IsRequired(required: true);
+
+ builder.Property(entity => entity.UpdatedOn)
+ .HasColumnName("updated_on")
+ .IsRequired(required: false);
+
+ builder
+ .HasMany(entity => entity.Transactions)
+ .WithOne(entity => entity.Payment)
+ .HasForeignKey(entity => entity.PaymentId)
+ .OnDelete(DeleteBehavior.Cascade);
}
-}
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/TransactionConfiguration.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/TransactionConfiguration.cs
index 61c46011..267d97db 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/TransactionConfiguration.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Configuration/TransactionConfiguration.cs
@@ -6,60 +6,59 @@
using Parbad.Storage.EntityFrameworkCore.Domain;
using Parbad.Storage.EntityFrameworkCore.Options;
-namespace Parbad.Storage.EntityFrameworkCore.Configuration
+namespace Parbad.Storage.EntityFrameworkCore.Configuration;
+
+///
+/// Transaction entity configuration.
+///
+public class TransactionConfiguration : EntityTypeConfiguration
{
///
- /// Transaction entity configuration.
+ /// Initializes an instance of .
///
- public class TransactionConfiguration : EntityTypeConfiguration
+ public TransactionConfiguration(EntityFrameworkCoreOptions efCoreOptions) : base(efCoreOptions)
{
- ///
- /// Initializes an instance of .
- ///
- public TransactionConfiguration(EntityFrameworkCoreOptions efCoreOptions) : base(efCoreOptions)
- {
- }
+ }
- ///
- public override void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions efCoreOptions)
- {
- builder.ToTable(efCoreOptions.TransactionTableOptions, efCoreOptions.DefaultSchema);
+ ///
+ public override void Configure(EntityTypeBuilder builder, EntityFrameworkCoreOptions efCoreOptions)
+ {
+ builder.ToTable(efCoreOptions.TransactionTableOptions, efCoreOptions.DefaultSchema);
- builder
- .HasKey(entity => entity.Id)
- .HasName("transaction_id");
- builder.Property(entity => entity.Id)
- .HasColumnName("transaction_id")
- .ValueGeneratedOnAdd();
+ builder
+ .HasKey(entity => entity.Id)
+ .HasName("transaction_id");
+ builder.Property(entity => entity.Id)
+ .HasColumnName("transaction_id")
+ .ValueGeneratedOnAdd();
- builder.Property(entity => entity.Amount)
- .HasColumnName(nameof(TransactionEntity.Amount).ToLower())
- .HasColumnType("decimal(18,2)")
- .IsRequired(required: true);
+ builder.Property(entity => entity.Amount)
+ .HasColumnName(nameof(TransactionEntity.Amount).ToLower())
+ .HasColumnType("decimal(18,2)")
+ .IsRequired(required: true);
- builder.Property(entity => entity.Type)
- .HasColumnName(nameof(TransactionEntity.Type).ToLower())
- .IsRequired(required: true);
+ builder.Property(entity => entity.Type)
+ .HasColumnName(nameof(TransactionEntity.Type).ToLower())
+ .IsRequired(required: true);
- builder.Property(entity => entity.IsSucceed)
- .HasColumnName("is_succeed")
- .IsRequired(required: true);
+ builder.Property(entity => entity.IsSucceed)
+ .HasColumnName("is_succeed")
+ .IsRequired(required: true);
- builder.Property(entity => entity.Message)
- .HasColumnName(nameof(TransactionEntity.Message).ToLower())
- .IsRequired(required: false);
+ builder.Property(entity => entity.Message)
+ .HasColumnName(nameof(TransactionEntity.Message).ToLower())
+ .IsRequired(required: false);
- builder.Property(entity => entity.AdditionalData)
- .HasColumnName("additional_data")
- .IsRequired(required: false);
+ builder.Property(entity => entity.AdditionalData)
+ .HasColumnName("additional_data")
+ .IsRequired(required: false);
- builder.Property(entity => entity.CreatedOn)
- .HasColumnName("created_on")
- .IsRequired(required: true);
+ builder.Property(entity => entity.CreatedOn)
+ .HasColumnName("created_on")
+ .IsRequired(required: true);
- builder.Property(entity => entity.UpdatedOn)
- .HasColumnName("updated_on")
- .IsRequired(required: false);
- }
+ builder.Property(entity => entity.UpdatedOn)
+ .HasColumnName("updated_on")
+ .IsRequired(required: false);
}
-}
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Context/ParbadDataContext.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Context/ParbadDataContext.cs
index ba18e094..856cb275 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Context/ParbadDataContext.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Context/ParbadDataContext.cs
@@ -7,26 +7,25 @@
using Parbad.Storage.EntityFrameworkCore.Domain;
using Parbad.Storage.EntityFrameworkCore.Options;
-namespace Parbad.Storage.EntityFrameworkCore.Context
+namespace Parbad.Storage.EntityFrameworkCore.Context;
+
+public class ParbadDataContext : DbContext
{
- public class ParbadDataContext : DbContext
+ public ParbadDataContext(DbContextOptions options, IOptions efCoreOptions)
+ : base(options)
{
- public ParbadDataContext(DbContextOptions options, IOptions efCoreOptions) : base(options)
- {
- EntityFrameworkCoreOptions = efCoreOptions.Value;
- }
+ EntityFrameworkCoreOptions = efCoreOptions.Value;
+ }
- public EntityFrameworkCoreOptions EntityFrameworkCoreOptions { get; }
+ public EntityFrameworkCoreOptions EntityFrameworkCoreOptions { get; }
- public DbSet Payments { get; set; }
+ public DbSet Payments { get; set; }
- public DbSet Transactions { get; set; }
+ public DbSet Transactions { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder
- .ApplyConfiguration(new PaymentConfiguration(EntityFrameworkCoreOptions))
- .ApplyConfiguration(new TransactionConfiguration(EntityFrameworkCoreOptions));
- }
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.ApplyConfiguration(new PaymentConfiguration(EntityFrameworkCoreOptions))
+ .ApplyConfiguration(new TransactionConfiguration(EntityFrameworkCoreOptions));
}
}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Domain/PaymentEntity.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Domain/PaymentEntity.cs
index 50edc535..23311e0e 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Domain/PaymentEntity.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Domain/PaymentEntity.cs
@@ -4,32 +4,31 @@
using System;
using System.Collections.Generic;
-namespace Parbad.Storage.EntityFrameworkCore.Domain
+namespace Parbad.Storage.EntityFrameworkCore.Domain;
+
+public class PaymentEntity
{
- public class PaymentEntity
- {
- public long Id { get; set; }
+ public long Id { get; set; }
- public long TrackingNumber { get; set; }
+ public long TrackingNumber { get; set; }
- public decimal Amount { get; set; }
+ public decimal Amount { get; set; }
- public string Token { get; set; }
+ public string Token { get; set; }
- public string TransactionCode { get; set; }
+ public string TransactionCode { get; set; }
- public string GatewayName { get; set; }
+ public string GatewayName { get; set; }
- public string GatewayAccountName { get; set; }
+ public string GatewayAccountName { get; set; }
- public bool IsCompleted { get; set; }
+ public bool IsCompleted { get; set; }
- public bool IsPaid { get; set; }
+ public bool IsPaid { get; set; }
- public DateTime CreatedOn { get; set; }
+ public DateTime CreatedOn { get; set; }
- public DateTime? UpdatedOn { get; set; }
+ public DateTime? UpdatedOn { get; set; }
- public List Transactions { get; set; } = new List();
- }
-}
+ public List Transactions { get; set; } = new List();
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Domain/TransactionEntity.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Domain/TransactionEntity.cs
index 5652e80d..fa19b4a6 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Domain/TransactionEntity.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Domain/TransactionEntity.cs
@@ -4,28 +4,27 @@
using Parbad.Storage.Abstractions.Models;
using System;
-namespace Parbad.Storage.EntityFrameworkCore.Domain
+namespace Parbad.Storage.EntityFrameworkCore.Domain;
+
+public class TransactionEntity
{
- public class TransactionEntity
- {
- public long Id { get; set; }
+ public long Id { get; set; }
- public decimal Amount { get; set; }
+ public decimal Amount { get; set; }
- public TransactionType Type { get; set; }
+ public TransactionType Type { get; set; }
- public bool IsSucceed { get; set; }
+ public bool IsSucceed { get; set; }
- public string Message { get; set; }
+ public string Message { get; set; }
- public string AdditionalData { get; set; }
+ public string AdditionalData { get; set; }
- public long PaymentId { get; set; }
+ public long PaymentId { get; set; }
- public DateTime CreatedOn { get; set; }
+ public DateTime CreatedOn { get; set; }
- public DateTime? UpdatedOn { get; set; }
+ public DateTime? UpdatedOn { get; set; }
- public PaymentEntity Payment { get; set; }
- }
-}
+ public PaymentEntity Payment { get; set; }
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorage.cs b/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorage.cs
index c6f4e4b9..304c07b8 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorage.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorage.cs
@@ -7,139 +7,183 @@
using Parbad.Storage.EntityFrameworkCore.Context;
using Parbad.Storage.EntityFrameworkCore.Internal;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace Parbad.Storage.EntityFrameworkCore
+namespace Parbad.Storage.EntityFrameworkCore;
+
+///
+/// EntityFramework Core implementation of .
+///
+public class EntityFrameworkCoreStorage : IStorage
{
///
- /// EntityFramework Core implementation of .
+ /// Initializes an instance of .
+ ///
+ ///
+ public EntityFrameworkCoreStorage(ParbadDataContext context)
+ {
+ Context = context;
+ }
+
+ ///
+ [Obsolete("This property will be removed in a future release. The usages are implemented as methods now.")]
+ public virtual IQueryable Payments => Context.Payments.Select(Mapper.ToPaymentModel());
+
+ ///
+ [Obsolete("This property will be removed in a future release. The usages are implemented as methods now.")]
+ public virtual IQueryable Transactions => Context.Transactions.Select(Mapper.ToTransactionModel());
+
+ ///
+ /// Gets Parbad DbContext.
///
- public class EntityFrameworkCoreStorage : IStorage
+ protected ParbadDataContext Context { get; }
+
+ ///
+ public virtual async Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
{
- ///
- /// Initializes an instance of .
- ///
- ///
- public EntityFrameworkCoreStorage(ParbadDataContext context)
- {
- Context = context;
- }
+ if (payment == null) throw new ArgumentNullException(nameof(payment));
+
+ var entity = payment.ToPaymentEntity();
+ entity.CreatedOn = DateTime.UtcNow;
+
+ Context.Payments.Add(entity);
+
+ await Context.SaveChangesAsync(cancellationToken);
- ///
- public virtual IQueryable Payments => Context.Payments.Select(Mapper.ToPaymentModel());
+ Context.Entry(entity).State = EntityState.Detached;
- ///
- public virtual IQueryable Transactions => Context.Transactions.Select(Mapper.ToTransactionModel());
+ payment.Id = entity.Id;
+ }
- ///
- /// Parbad DbContext.
- ///
- protected ParbadDataContext Context { get; }
+ ///
+ public virtual async Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
+ {
+ if (payment == null) throw new ArgumentNullException(nameof(payment));
- ///
- public virtual async Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- if (payment == null) throw new ArgumentNullException(nameof(payment));
+ var record = await Context
+ .Payments
+ .AsNoTracking()
+ .SingleOrDefaultAsync(model => model.Id == payment.Id, cancellationToken);
- var entity = payment.ToPaymentEntity();
- entity.CreatedOn = DateTime.UtcNow;
+ if (record == null) throw new InvalidOperationException($"No payment records found in database with id {payment.Id}");
- Context.Payments.Add(entity);
+ Mapper.ToPaymentEntity(payment, record);
+ record.UpdatedOn = DateTime.UtcNow;
- await Context.SaveChangesAsync(cancellationToken);
+ Context.Payments.Update(record);
- Context.Entry(entity).State = EntityState.Detached;
+ await Context.SaveChangesAsync(cancellationToken);
+ }
- payment.Id = entity.Id;
- }
+ ///
+ public virtual async Task DeletePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
+ {
+ if (payment == null) throw new ArgumentNullException(nameof(payment));
- ///
- public virtual async Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- if (payment == null) throw new ArgumentNullException(nameof(payment));
+ var record = await Context
+ .Payments
+ .AsNoTracking()
+ .SingleOrDefaultAsync(model => model.Id == payment.Id, cancellationToken);
- var record = await Context
- .Payments
- .AsNoTracking()
- .SingleOrDefaultAsync(model => model.Id == payment.Id, cancellationToken);
+ if (record == null) throw new InvalidOperationException($"No payment records found in database with id {payment.Id}");
- if (record == null) throw new InvalidOperationException($"No payment records found in database with id {payment.Id}");
+ Context.Payments.Remove(record);
- Mapper.ToPaymentEntity(payment, record);
- record.UpdatedOn = DateTime.UtcNow;
+ await Context.SaveChangesAsync(cancellationToken);
+ }
- Context.Payments.Update(record);
+ ///
+ public virtual async Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
+ {
+ if (transaction == null) throw new ArgumentNullException(nameof(transaction));
- await Context.SaveChangesAsync(cancellationToken);
- }
+ var entity = transaction.ToTransactionEntity();
+ entity.CreatedOn = DateTime.UtcNow;
- ///
- public virtual async Task DeletePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- if (payment == null) throw new ArgumentNullException(nameof(payment));
+ Context.Transactions.Add(entity);
- var record = await Context
- .Payments
- .AsNoTracking()
- .SingleOrDefaultAsync(model => model.Id == payment.Id, cancellationToken);
+ await Context.SaveChangesAsync(cancellationToken);
- if (record == null) throw new InvalidOperationException($"No payment records found in database with id {payment.Id}");
+ transaction.Id = entity.Id;
+ }
- Context.Payments.Remove(record);
+ ///
+ public virtual async Task UpdateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
+ {
+ if (transaction == null) throw new ArgumentNullException(nameof(transaction));
- await Context.SaveChangesAsync(cancellationToken);
- }
+ var record = await Context
+ .Transactions
+ .SingleOrDefaultAsync(model => model.Id == transaction.Id, cancellationToken);
- ///
- public virtual async Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
- {
- if (transaction == null) throw new ArgumentNullException(nameof(transaction));
+ if (record == null) throw new InvalidOperationException($"No transaction records found in database with id {transaction.Id}");
- var entity = transaction.ToTransactionEntity();
- entity.CreatedOn = DateTime.UtcNow;
+ Mapper.ToTransactionEntity(transaction, record);
+ record.UpdatedOn = DateTime.UtcNow;
- Context.Transactions.Add(entity);
+ Context.Transactions.Update(record);
- await Context.SaveChangesAsync(cancellationToken);
+ await Context.SaveChangesAsync(cancellationToken);
+ }
- transaction.Id = entity.Id;
- }
+ ///
+ public virtual async Task DeleteTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
+ {
+ if (transaction == null) throw new ArgumentNullException(nameof(transaction));
- ///
- public virtual async Task UpdateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
- {
- if (transaction == null) throw new ArgumentNullException(nameof(transaction));
+ var record = await Context
+ .Transactions
+ .SingleOrDefaultAsync(model => model.Id == transaction.Id, cancellationToken);
- var record = await Context
- .Transactions
- .SingleOrDefaultAsync(model => model.Id == transaction.Id, cancellationToken);
+ if (record == null) throw new InvalidOperationException($"No transaction records found in database with id {transaction.Id}");
- if (record == null) throw new InvalidOperationException($"No transaction records found in database with id {transaction.Id}");
+ Context.Transactions.Remove(record);
- Mapper.ToTransactionEntity(transaction, record);
- record.UpdatedOn = DateTime.UtcNow;
+ await Context.SaveChangesAsync(cancellationToken);
+ }
- Context.Transactions.Update(record);
+ ///
+ public virtual async Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default)
+ {
+ var paymentEntity = await Context.Payments
+ .AsNoTracking()
+ .SingleOrDefaultAsync(payment => payment.TrackingNumber == trackingNumber, cancellationToken);
- await Context.SaveChangesAsync(cancellationToken);
- }
+ return paymentEntity?.ToPaymentModel();
+ }
- ///
- public virtual async Task DeleteTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
- {
- if (transaction == null) throw new ArgumentNullException(nameof(transaction));
+ ///
+ public virtual async Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default)
+ {
+ var paymentEntity = await Context.Payments
+ .AsNoTracking()
+ .SingleOrDefaultAsync(payment => payment.Token == paymentToken, cancellationToken);
- var record = await Context
- .Transactions
- .SingleOrDefaultAsync(model => model.Id == transaction.Id, cancellationToken);
+ return paymentEntity?.ToPaymentModel();
+ }
- if (record == null) throw new InvalidOperationException($"No transaction records found in database with id {transaction.Id}");
+ ///
+ public virtual Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default)
+ {
+ return Context.Payments.AnyAsync(payment => payment.TrackingNumber == trackingNumber, cancellationToken);
+ }
- Context.Transactions.Remove(record);
+ ///
+ public virtual Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default)
+ {
+ return Context.Payments.AnyAsync(payment => payment.Token == paymentToken, cancellationToken);
+ }
- await Context.SaveChangesAsync(cancellationToken);
- }
+ ///
+ public virtual Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default)
+ {
+ return Context.Transactions
+ .Where(transaction => transaction.PaymentId == payment.Id)
+ .AsNoTracking()
+ .Select(Mapper.ToTransactionModel())
+ .ToListAsync(cancellationToken);
}
}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorageManager.cs b/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorageManager.cs
index 90288a8c..01517ee4 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorageManager.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/EntityFrameworkCoreStorageManager.cs
@@ -1,82 +1,11 @@
-using Microsoft.EntityFrameworkCore;
+using System;
using Parbad.Storage.Abstractions;
-using Parbad.Storage.Abstractions.Models;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
+using Parbad.Storage.EntityFrameworkCore.Context;
-namespace Parbad.Storage.EntityFrameworkCore
-{
- ///
- /// EntityFramework Core implementation of .
- ///
- public class EntityFrameworkCoreStorageManager : IStorageManager
- {
- ///
- /// Initializes an instance of .
- ///
- ///
- public EntityFrameworkCoreStorageManager(IStorage storage)
- {
- Storage = storage;
- }
+namespace Parbad.Storage.EntityFrameworkCore;
- protected readonly IStorage Storage;
-
- ///
- public virtual Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- return Storage.CreatePaymentAsync(payment, cancellationToken);
- }
-
- ///
- public virtual Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- return Storage.UpdatePaymentAsync(payment, cancellationToken);
- }
-
- ///
- public virtual Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
- {
- return Storage.CreateTransactionAsync(transaction, cancellationToken);
- }
-
- ///
- public virtual Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default)
- {
- return Storage.Payments
- .AsNoTracking()
- .SingleOrDefaultAsync(payment => payment.TrackingNumber == trackingNumber, cancellationToken);
- }
-
- ///
- public virtual Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default)
- {
- return Storage.Payments
- .AsNoTracking()
- .SingleOrDefaultAsync(payment => payment.Token == paymentToken, cancellationToken);
- }
-
- ///
- public virtual Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default)
- {
- return Storage.Payments.AnyAsync(payment => payment.TrackingNumber == trackingNumber, cancellationToken);
- }
-
- ///
- public virtual Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default)
- {
- return Storage.Payments.AnyAsync(payment => payment.Token == paymentToken, cancellationToken);
- }
-
- ///
- public virtual Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- return Storage.Transactions
- .Where(transaction => transaction.PaymentId == payment.Id)
- .AsNoTracking()
- .ToListAsync(cancellationToken);
- }
- }
-}
+///
+/// EntityFramework Core implementation of .
+///
+[Obsolete("This class will be removed in a future release. The implementations are moved to the EntityFrameworkCoreStorage class.")]
+public class EntityFrameworkCoreStorageManager(ParbadDataContext context) : EntityFrameworkCoreStorage(context), IStorageManager;
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Internal/Mapper.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Internal/Mapper.cs
index dc89b858..cf4e9910 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Internal/Mapper.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Internal/Mapper.cs
@@ -6,87 +6,104 @@
using System;
using System.Linq.Expressions;
-namespace Parbad.Storage.EntityFrameworkCore.Internal
+namespace Parbad.Storage.EntityFrameworkCore.Internal;
+
+internal static class Mapper
{
- internal static class Mapper
+ public static PaymentEntity ToPaymentEntity(this Payment model)
{
- public static PaymentEntity ToPaymentEntity(this Payment model)
- {
- return new PaymentEntity
- {
- TrackingNumber = model.TrackingNumber,
- Amount = model.Amount,
- Token = model.Token,
- TransactionCode = model.TransactionCode,
- GatewayName = model.GatewayName,
- GatewayAccountName = model.GatewayAccountName,
- IsCompleted = model.IsCompleted,
- IsPaid = model.IsPaid
- };
- }
+ return new PaymentEntity
+ {
+ TrackingNumber = model.TrackingNumber,
+ Amount = model.Amount,
+ Token = model.Token,
+ TransactionCode = model.TransactionCode,
+ GatewayName = model.GatewayName,
+ GatewayAccountName = model.GatewayAccountName,
+ IsCompleted = model.IsCompleted,
+ IsPaid = model.IsPaid
+ };
+ }
- public static void ToPaymentEntity(Payment model, PaymentEntity entity)
- {
- entity.TrackingNumber = model.TrackingNumber;
- entity.Amount = model.Amount;
- entity.Token = model.Token;
- entity.TransactionCode = model.TransactionCode;
- entity.GatewayName = model.GatewayName;
- entity.GatewayAccountName = model.GatewayAccountName;
- entity.IsCompleted = model.IsCompleted;
- entity.IsPaid = model.IsPaid;
- }
+ public static void ToPaymentEntity(Payment model, PaymentEntity entity)
+ {
+ entity.TrackingNumber = model.TrackingNumber;
+ entity.Amount = model.Amount;
+ entity.Token = model.Token;
+ entity.TransactionCode = model.TransactionCode;
+ entity.GatewayName = model.GatewayName;
+ entity.GatewayAccountName = model.GatewayAccountName;
+ entity.IsCompleted = model.IsCompleted;
+ entity.IsPaid = model.IsPaid;
+ }
- public static Expression> ToPaymentModel()
- {
- return entity => new Payment
- {
- Id = entity.Id,
- TrackingNumber = entity.TrackingNumber,
- Amount = entity.Amount,
- Token = entity.Token,
- TransactionCode = entity.TransactionCode,
- GatewayName = entity.GatewayName,
- GatewayAccountName = entity.GatewayAccountName,
- IsCompleted = entity.IsCompleted,
- IsPaid = entity.IsPaid
- };
- }
+ public static Expression> ToPaymentModel()
+ {
+ return entity => new Payment
+ {
+ Id = entity.Id,
+ TrackingNumber = entity.TrackingNumber,
+ Amount = entity.Amount,
+ Token = entity.Token,
+ TransactionCode = entity.TransactionCode,
+ GatewayName = entity.GatewayName,
+ GatewayAccountName = entity.GatewayAccountName,
+ IsCompleted = entity.IsCompleted,
+ IsPaid = entity.IsPaid
+ };
+ }
- public static TransactionEntity ToTransactionEntity(this Transaction model)
- {
- return new TransactionEntity
- {
- Amount = model.Amount,
- Type = model.Type,
- IsSucceed = model.IsSucceed,
- Message = model.Message,
- AdditionalData = model.AdditionalData,
- PaymentId = model.PaymentId
- };
- }
+ public static Payment ToPaymentModel(this PaymentEntity paymentEntity)
+ {
+ if (paymentEntity == null) throw new ArgumentNullException(nameof(paymentEntity));
- public static void ToTransactionEntity(Transaction model, TransactionEntity entity)
- {
- entity.Amount = model.Amount;
- entity.Type = model.Type;
- entity.IsSucceed = model.IsSucceed;
- entity.Message = model.Message;
- entity.AdditionalData = model.AdditionalData;
- }
+ return new()
+ {
+ Id = paymentEntity.Id,
+ TrackingNumber = paymentEntity.TrackingNumber,
+ Amount = paymentEntity.Amount,
+ Token = paymentEntity.Token,
+ TransactionCode = paymentEntity.TransactionCode,
+ GatewayName = paymentEntity.GatewayName,
+ GatewayAccountName = paymentEntity.GatewayAccountName,
+ IsCompleted = paymentEntity.IsCompleted,
+ IsPaid = paymentEntity.IsPaid
+ };
+ }
- public static Expression> ToTransactionModel()
- {
- return entity => new Transaction
- {
- Id = entity.Id,
- Amount = entity.Amount,
- Type = entity.Type,
- IsSucceed = entity.IsSucceed,
- Message = entity.Message,
- AdditionalData = entity.AdditionalData,
- PaymentId = entity.PaymentId
- };
- }
+ public static TransactionEntity ToTransactionEntity(this Transaction model)
+ {
+ return new TransactionEntity
+ {
+ Amount = model.Amount,
+ Type = model.Type,
+ IsSucceed = model.IsSucceed,
+ Message = model.Message,
+ AdditionalData = model.AdditionalData,
+ PaymentId = model.PaymentId
+ };
+ }
+
+ public static void ToTransactionEntity(Transaction model, TransactionEntity entity)
+ {
+ entity.Amount = model.Amount;
+ entity.Type = model.Type;
+ entity.IsSucceed = model.IsSucceed;
+ entity.Message = model.Message;
+ entity.AdditionalData = model.AdditionalData;
+ }
+
+ public static Expression> ToTransactionModel()
+ {
+ return entity => new Transaction
+ {
+ Id = entity.Id,
+ Amount = entity.Amount,
+ Type = entity.Type,
+ IsSucceed = entity.IsSucceed,
+ Message = entity.Message,
+ AdditionalData = entity.AdditionalData,
+ PaymentId = entity.PaymentId
+ };
}
}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Options/EntityFrameworkCoreOptions.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Options/EntityFrameworkCoreOptions.cs
index eca0f5f0..a59cd4d7 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Options/EntityFrameworkCoreOptions.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Options/EntityFrameworkCoreOptions.cs
@@ -5,43 +5,42 @@
using Microsoft.EntityFrameworkCore;
using Parbad.Storage.EntityFrameworkCore.Context;
-namespace Parbad.Storage.EntityFrameworkCore.Options
+namespace Parbad.Storage.EntityFrameworkCore.Options;
+
+///
+/// Contains the options for configuring the EntityFrameworkCore for Parbad storage.
+///
+public class EntityFrameworkCoreOptions
{
///
- /// Contains the options for configuring the EntityFrameworkCore for Parbad storage.
+ /// Initializes an instance of .
///
- public class EntityFrameworkCoreOptions
+ public EntityFrameworkCoreOptions()
{
- ///
- /// Initializes an instance of .
- ///
- public EntityFrameworkCoreOptions()
- {
- DefaultSchema = "parbad";
-
- PaymentTableOptions = new TableOptions { Name = "payment" };
-
- TransactionTableOptions = new TableOptions { Name = "transaction" };
- }
-
- ///
- /// Configures the .
- ///
- public Action ConfigureDbContext { get; set; }
-
- ///
- /// Gets or sets the default schema for all tables. The default value is "parbad".
- ///
- public string DefaultSchema { get; set; }
-
- ///
- /// Contains the options for configuring the Payment table.
- ///
- public TableOptions PaymentTableOptions { get; set; }
-
- ///
- /// Contains the options for configuring the Transaction table.
- ///
- public TableOptions TransactionTableOptions { get; set; }
+ DefaultSchema = "parbad";
+
+ PaymentTableOptions = new TableOptions { Name = "payment" };
+
+ TransactionTableOptions = new TableOptions { Name = "transaction" };
}
+
+ ///
+ /// Configures the .
+ ///
+ public Action ConfigureDbContext { get; set; }
+
+ ///
+ /// Gets or sets the default schema for all tables. The default value is "parbad".
+ ///
+ public string DefaultSchema { get; set; }
+
+ ///
+ /// Contains the options for configuring the Payment table.
+ ///
+ public TableOptions PaymentTableOptions { get; set; }
+
+ ///
+ /// Contains the options for configuring the Transaction table.
+ ///
+ public TableOptions TransactionTableOptions { get; set; }
}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Options/TableOptions.cs b/src/Parbad.Storage/EntityFrameworkCore/src/Options/TableOptions.cs
index 38a750b3..da54885f 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Options/TableOptions.cs
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Options/TableOptions.cs
@@ -1,21 +1,20 @@
// Copyright (c) Parbad. All rights reserved.
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
-namespace Parbad.Storage.EntityFrameworkCore.Options
+namespace Parbad.Storage.EntityFrameworkCore.Options;
+
+///
+/// Contains the options for configuring a table.
+///
+public class TableOptions
{
///
- /// Contains the options for configuring a table.
+ /// Gets or sets the name.
///
- public class TableOptions
- {
- ///
- /// Gets or sets the name.
- ///
- public string Name { get; set; }
+ public string Name { get; set; }
- ///
- /// Gets or sets the schema.
- ///
- public string Schema { get; set; }
- }
-}
+ ///
+ /// Gets or sets the schema.
+ ///
+ public string Schema { get; set; }
+}
\ No newline at end of file
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityFrameworkCore.csproj b/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityFrameworkCore.csproj
index a536457f..75ef88b5 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityFrameworkCore.csproj
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityFrameworkCore.csproj
@@ -2,9 +2,10 @@
Parbad.Storage.EntityFrameworkCore
- 1.5.0
+ 1.6.0
latest
- net5;net6;net7;net8.0
+ net5;net6;net7;net8.0;net9.0
+ enable
false
true
LGPL-3.0-or-later
@@ -19,7 +20,7 @@ More information: https://github.com/Sina-Soltani/Parbad
true
Sina Soltani
Parbad.Storage.EntityframeworkCore
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
diff --git a/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityframeworkCore.xml b/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityframeworkCore.xml
index 1a0f2bfd..19462b5c 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityframeworkCore.xml
+++ b/src/Parbad.Storage/EntityFrameworkCore/src/Parbad.Storage.EntityframeworkCore.xml
@@ -89,7 +89,7 @@
- Parbad DbContext.
+ Gets Parbad DbContext.
@@ -110,40 +110,30 @@
-
-
- EntityFramework Core implementation of .
-
-
-
-
- Initializes an instance of .
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
-
+
+
+ EntityFramework Core implementation of .
+
-
-
+
+
+ EntityFramework Core implementation of .
+
diff --git a/src/Parbad.Storage/EntityFrameworkCore/tests/EntityFrameworkStorageManagerTests.cs b/src/Parbad.Storage/EntityFrameworkCore/tests/EntityFrameworkStorageManagerTests.cs
deleted file mode 100644
index 7d12083d..00000000
--- a/src/Parbad.Storage/EntityFrameworkCore/tests/EntityFrameworkStorageManagerTests.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using KellermanSoftware.CompareNetObjects;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Options;
-using Parbad.Storage.Abstractions.Models;
-using Parbad.Storage.EntityFrameworkCore.Context;
-using Parbad.Storage.EntityFrameworkCore.Options;
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Parbad.Storage.EntityFrameworkCore.Tests
-{
- [TestClass]
- public class EntityFrameworkStorageManagerTests
- {
- private ParbadDataContext _context;
- private EntityFrameworkCoreStorageManager _storageManager;
-
- private static readonly Payment PaymentTestData = new Payment
- {
- TrackingNumber = 1,
- Amount = 1,
- Token = "token",
- GatewayAccountName = "default",
- GatewayName = "gateway",
- IsCompleted = true,
- IsPaid = false,
- TransactionCode = "code"
- };
-
- [TestInitialize]
- public void Setup()
- {
- var contextOptions = new DbContextOptionsBuilder()
- .UseInMemoryDatabase(Guid.NewGuid().ToString())
- .Options;
-
- var efCoreOptions = new OptionsWrapper(new EntityFrameworkCoreOptions());
-
- _context = new ParbadDataContext(contextOptions, efCoreOptions);
-
- var storage = new EntityFrameworkCoreStorage(_context);
-
- _storageManager = new EntityFrameworkCoreStorageManager(storage);
- }
-
- [TestCleanup]
- public ValueTask Cleanup()
- {
- return _context.DisposeAsync();
- }
-
- [TestMethod]
- public async Task GetPaymentByTrackingNumber_Must_Be_Equal_With_Expected_Payment_Object()
- {
- await _storageManager.CreatePaymentAsync(PaymentTestData);
-
- var payment = await _storageManager.GetPaymentByTrackingNumberAsync(PaymentTestData.TrackingNumber);
-
- Assert.IsNotNull(payment);
-
- payment.ShouldCompare(PaymentTestData, "Payment is not equal with the expected Payment object.");
- }
-
- [TestMethod]
- public async Task GetPaymentByToken_Must_Be_Equal_With_Expected_Payment_Object()
- {
- await _storageManager.CreatePaymentAsync(PaymentTestData);
-
- var payment = await _storageManager.GetPaymentByTokenAsync(PaymentTestData.Token);
-
- Assert.IsNotNull(payment);
-
- payment.ShouldCompare(PaymentTestData, "Payment is not equal with the expected Payment object.");
- }
-
- [TestMethod]
- public async Task DoesPaymentExists_By_Token_Must_Be_True()
- {
- await _storageManager.CreatePaymentAsync(PaymentTestData);
-
- var exist = await _storageManager.DoesPaymentExistAsync(PaymentTestData.Token);
-
- Assert.IsTrue(exist);
- }
-
- [TestMethod]
- public async Task DoesPaymentExists_By_TrackingNumber_Must_Be_True()
- {
- await _storageManager.CreatePaymentAsync(PaymentTestData);
-
- var exist = await _storageManager.DoesPaymentExistAsync(PaymentTestData.TrackingNumber);
-
- Assert.IsTrue(exist);
- }
-
- [TestMethod]
- public async Task GetTransactions_Must_Be_Equal_With_Expected_Transactions()
- {
- await _storageManager.CreatePaymentAsync(PaymentTestData);
-
- var expectedTransactions = new List
- {
- new Transaction
- {
- Amount = 1000,
- IsSucceed = false,
- Message = "test",
- Type = TransactionType.Request,
- AdditionalData = "test",
- PaymentId = PaymentTestData.Id
- },
- new Transaction
- {
- Amount = 1000,
- IsSucceed = false,
- Message = "test",
- Type = TransactionType.Verify,
- AdditionalData = "test",
- PaymentId = PaymentTestData.Id
- },
- new Transaction
- {
- Amount = 1000,
- IsSucceed = false,
- Message = "test",
- Type = TransactionType.Refund,
- AdditionalData = "test",
- PaymentId = PaymentTestData.Id
- }
- };
-
- foreach (var transaction in expectedTransactions)
- {
- await _storageManager.CreateTransactionAsync(transaction);
- }
-
- var transactions = await _storageManager.GetTransactionsAsync(PaymentTestData);
-
- Assert.IsNotNull(transactions);
- Assert.AreEqual(expectedTransactions.Count, transactions.Count);
- transactions.ShouldCompare(expectedTransactions);
- }
- }
-}
diff --git a/src/Parbad.Storage/EntityFrameworkCore/tests/Parbad.Storage.EntityFrameworkCore.Tests.csproj b/src/Parbad.Storage/EntityFrameworkCore/tests/Parbad.Storage.EntityFrameworkCore.Tests.csproj
index de160849..67d0a9a2 100644
--- a/src/Parbad.Storage/EntityFrameworkCore/tests/Parbad.Storage.EntityFrameworkCore.Tests.csproj
+++ b/src/Parbad.Storage/EntityFrameworkCore/tests/Parbad.Storage.EntityFrameworkCore.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
false
diff --git a/src/Parbad/src/Abstraction/Invoice.cs b/src/Parbad/src/Abstraction/Invoice.cs
index 914d9209..6b893864 100644
--- a/src/Parbad/src/Abstraction/Invoice.cs
+++ b/src/Parbad/src/Abstraction/Invoice.cs
@@ -3,50 +3,48 @@
using System.Collections.Generic;
-namespace Parbad.Abstraction
+namespace Parbad.Abstraction;
+
+///
+/// Describes an invoice which must be requested.
+///
+public class Invoice
{
///
/// Describes an invoice which must be requested.
///
- public class Invoice
+ public Invoice()
{
- ///
- /// Describes an invoice which must be requested.
- ///
- public Invoice()
- {
- Properties = new Dictionary();
- }
-
- ///
- /// Gets or sets the Tracking number of the invoice.
- ///
- public long TrackingNumber { get; set; }
-
- ///
- /// Gets or sets the amount of the invoice.
- /// Note: You can also enter long and decimal numbers. It can also be parsed to long and decimal.
- /// Examples:
- /// long a = invoice.Amount;
- /// decimal a = invoice.Amount;
- ///
- public Money Amount { get; set; }
-
- ///
- /// A complete URL of your website. It will be used by the gateway for redirecting
- /// the client again to your website.
- /// Note: A complete URL would be like: "http://www.mywebsite.com/foo/bar/"
- ///
- public CallbackUrl CallbackUrl { get; set; }
-
- ///
- /// Gets or sets the name of the gateway which the invoice must be paid in.
- ///
- public string GatewayName { get; set; }
-
- ///
- /// Gets or sets the properties of the invoice.
- ///
- public IDictionary Properties { get; set; }
}
+
+ ///
+ /// Gets or sets the Tracking number of the invoice.
+ ///
+ public long TrackingNumber { get; set; }
+
+ ///
+ /// Gets or sets the amount of the invoice.
+ /// Note: You can also enter long and decimal numbers. It can also be parsed to long and decimal.
+ /// Examples:
+ /// long a = invoice.Amount;
+ /// decimal a = invoice.Amount;
+ ///
+ public Money Amount { get; set; }
+
+ ///
+ /// A complete URL of your website. It will be used by the gateway for redirecting
+ /// the client again to your website.
+ /// Note: A complete URL would be like: "http://www.mywebsite.com/foo/bar/"
+ ///
+ public CallbackUrl CallbackUrl { get; set; }
+
+ ///
+ /// Gets or sets the name of the gateway which the invoice must be paid in.
+ ///
+ public string GatewayName { get; set; }
+
+ ///
+ /// Gets or sets the properties of the invoice.
+ ///
+ public IDictionary Properties { get; set; } = new Dictionary();
}
diff --git a/src/Parbad/src/Gateway/ParbadVirtual/ParbadVirtualGatewayStyles.css b/src/Parbad/src/Gateway/ParbadVirtual/ParbadVirtualGatewayStyles.css
index 32f955c8..77fcda9b 100644
--- a/src/Parbad/src/Gateway/ParbadVirtual/ParbadVirtualGatewayStyles.css
+++ b/src/Parbad/src/Gateway/ParbadVirtual/ParbadVirtualGatewayStyles.css
@@ -73,7 +73,7 @@ body {
}
.copyright {
- margin-top: 20px;
+ margin: 20px 0 20px 0;
color: white;
font-size: .9rem;
}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/IPasargadApi.cs b/src/Parbad/src/Gateway/Pasargad/Api/IPasargadApi.cs
new file mode 100644
index 00000000..c537e674
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/IPasargadApi.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+using System.Threading;
+using System.Threading.Tasks;
+using Parbad.Gateway.Pasargad.Api.Models;
+
+namespace Parbad.Gateway.Pasargad.Api;
+
+///
+/// API provided by Pasargad Bank.
+///
+public interface IPasargadApi
+{
+ ///
+ /// Gets a token to start a payment request.
+ ///
+ Task GetToken(PasargadGetTokenRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken);
+
+ ///
+ /// Verifies a payment.
+ ///
+ Task VerifyPayment(PasargadVerifyPaymentRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken);
+
+ ///
+ /// Refunds an already paid invoice.
+ ///
+ Task RefundPayment(PasargadRefundPaymentRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken);
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenRequestModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenRequestModel.cs
new file mode 100644
index 00000000..271a5a6d
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenRequestModel.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+using Newtonsoft.Json;
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadGetTokenRequestModel
+{
+ public string InvoiceNumber { get; set; }
+
+ public string InvoiceDate { get; set; }
+
+ public string TerminalCode { get; set; }
+
+ public string MerchantCode { get; set; }
+
+ public decimal Amount { get; set; }
+
+ public string RedirectAddress { get; set; }
+
+ public string Timestamp { get; set; }
+
+ public string Action => "1003";
+
+ public string Mobile { get; set; }
+
+ public string Email { get; set; }
+
+ public string MerchantName { get; set; }
+
+ [JsonProperty("PIDN")]
+ public string Pidn { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenResponseModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenResponseModel.cs
new file mode 100644
index 00000000..2ad51da7
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadGetTokenResponseModel.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadGetTokenResponseModel
+{
+ public bool IsSuccess { get; set; }
+
+ public string Message { get; set; }
+
+ public string Token { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentRequestModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentRequestModel.cs
new file mode 100644
index 00000000..9d63ff4f
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentRequestModel.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadRefundPaymentRequestModel
+{
+ public string InvoiceNumber { get; set; }
+
+ public string InvoiceDate { get; set; }
+
+ public string TerminalCode { get; set; }
+
+ public string MerchantCode { get; set; }
+
+ public string Timestamp { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentResponseModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentResponseModel.cs
new file mode 100644
index 00000000..f03b7620
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadRefundPaymentResponseModel.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadRefundPaymentResponseModel
+{
+ public bool IsSuccess { get; set; }
+
+ public string Message { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentRequestModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentRequestModel.cs
new file mode 100644
index 00000000..b37d5f70
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentRequestModel.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadVerifyPaymentRequestModel
+{
+ public string InvoiceNumber { get; set; }
+
+ public string InvoiceDate { get; set; }
+
+ public string TerminalCode { get; set; }
+
+ public string MerchantCode { get; set; }
+
+ public decimal Amount { get; set; }
+
+ public string Timestamp { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentResponseModel.cs b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentResponseModel.cs
new file mode 100644
index 00000000..9b90d73c
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Api/Models/PasargadVerifyPaymentResponseModel.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Api.Models;
+
+public class PasargadVerifyPaymentResponseModel
+{
+ public bool IsSuccess { get; set; }
+
+ public string Message { get; set; }
+
+ public string MaskedCardNumber { get; set; }
+
+ public string HashedCardNumber { get; set; }
+
+ public string ShaparakRefNumber { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/IPasargadCrypto.cs b/src/Parbad/src/Gateway/Pasargad/IPasargadCrypto.cs
index 61d9bc1b..0550735e 100644
--- a/src/Parbad/src/Gateway/Pasargad/IPasargadCrypto.cs
+++ b/src/Parbad/src/Gateway/Pasargad/IPasargadCrypto.cs
@@ -1,7 +1,15 @@
-namespace Parbad.Gateway.Pasargad
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad;
+
+///
+/// An Encryptor to sign data which will be sent by each request to Pasargad gateway.
+///
+public interface IPasargadCrypto
{
- public interface IPasargadCrypto
- {
- string Encrypt(string privateKey, string data);
- }
+ ///
+ /// Encrypts the given data using the provided Private Key.
+ ///
+ string Encrypt(string privateKey, string data);
}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResult.cs b/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResult.cs
deleted file mode 100644
index d3c000ae..00000000
--- a/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResult.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Parbad. All rights reserved.
-// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
-
-using System.Collections.Generic;
-
-namespace Parbad.Gateway.Pasargad.Internal.Models
-{
- internal class PasargadCallbackResult
- {
- public bool IsSucceed { get; set; }
-
- ///
- /// Equals to ReferenceID in Parbad system.
- ///
- public string InvoiceNumber { get; set; }
-
- public string InvoiceDate { get; set; }
-
- public string TransactionId { get; set; }
-
- public IEnumerable> CallbackCheckData { get; set; }
-
- public string Message { get; set; }
- }
-}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResultModel.cs b/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResultModel.cs
new file mode 100644
index 00000000..3ac4df33
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCallbackResultModel.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad.Internal.Models;
+
+internal class PasargadCallbackResultModel
+{
+ public bool IsSucceed => !string.IsNullOrWhiteSpace(InvoiceNumber) &&
+ !string.IsNullOrWhiteSpace(InvoiceDate) &&
+ !string.IsNullOrWhiteSpace(TransactionReferenceId);
+
+ public string InvoiceNumber { get; set; }
+
+ public string InvoiceDate { get; set; }
+
+ public string TransactionReferenceId { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCheckCallbackResult.cs b/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCheckCallbackResult.cs
deleted file mode 100644
index 48bec106..00000000
--- a/src/Parbad/src/Gateway/Pasargad/Internal/Models/PasargadCheckCallbackResult.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) Parbad. All rights reserved.
-// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
-
-using Parbad.Internal;
-
-namespace Parbad.Gateway.Pasargad.Internal.Models
-{
- internal class PasargadCheckCallbackResult
- {
- public bool IsSucceed { get; set; }
-
- public PaymentVerifyResult Result { get; set; }
- }
-}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/PasargadApi.cs b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadApi.cs
new file mode 100644
index 00000000..c6a3881f
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadApi.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using Parbad.Gateway.Pasargad.Api;
+using Parbad.Gateway.Pasargad.Api.Models;
+using Parbad.Net;
+
+namespace Parbad.Gateway.Pasargad.Internal;
+
+internal class PasargadApi : IPasargadApi
+{
+ private readonly HttpClient _httpClient;
+ private readonly PasargadGatewayOptions _options;
+ private readonly IPasargadCrypto _crypto;
+
+ public PasargadApi(HttpClient httpClient,
+ IOptions options,
+ IPasargadCrypto crypto)
+ {
+ _httpClient = httpClient;
+ _crypto = crypto;
+ _options = options.Value;
+ }
+
+ public Task GetToken(PasargadGetTokenRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken)
+ {
+ return PostJsonAsync(_options.ApiGetTokenUrl, model, privateKey, cancellationToken);
+ }
+
+ public Task VerifyPayment(PasargadVerifyPaymentRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken)
+ {
+ return PostJsonAsync(_options.ApiVerificationUrl, model, privateKey, cancellationToken);
+ }
+
+ public Task RefundPayment(PasargadRefundPaymentRequestModel model,
+ string privateKey,
+ CancellationToken cancellationToken)
+ {
+ return PostJsonAsync(_options.ApiRefundUrl, model, privateKey, cancellationToken);
+ }
+
+ private Task PostJsonAsync(string url,
+ object request,
+ string privateKey,
+ CancellationToken cancellationToken)
+ {
+ var json = JsonConvert.SerializeObject(request);
+
+ var sign = _crypto.Encrypt(privateKey, json);
+
+ AddDefaultHeaders(sign);
+
+ return _httpClient.PostJsonAsync(url, request, cancellationToken: cancellationToken);
+ }
+
+ private void AddDefaultHeaders(string sign)
+ {
+ _httpClient.DefaultRequestHeaders.Accept.Clear();
+ _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+
+ _httpClient.DefaultRequestHeaders.AddOrUpdate("Sign", sign);
+ }
+}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/PasargadCrypto.cs b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadCrypto.cs
index 10e04c2e..8f7e6c39 100644
--- a/src/Parbad/src/Gateway/Pasargad/Internal/PasargadCrypto.cs
+++ b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadCrypto.cs
@@ -1,26 +1,28 @@
-using System;
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+using System;
using System.Security.Cryptography;
using System.Text;
using Parbad.Utilities;
-namespace Parbad.Gateway.Pasargad.Internal
+namespace Parbad.Gateway.Pasargad.Internal;
+
+internal class PasargadCrypto : IPasargadCrypto
{
- internal class PasargadCrypto : IPasargadCrypto
+ public string Encrypt(string privateKey, string data)
{
- public string Encrypt(string privateKey, string data)
+ using (var rsa = new RSACryptoServiceProvider())
{
- using (var rsa = new RSACryptoServiceProvider())
- {
- byte[] encryptedData;
+ byte[] encryptedData;
#if NETSTANDARD2_0
rsa.FromXml(privateKey);
encryptedData = rsa.SignData(Encoding.UTF8.GetBytes(data), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
#else
- rsa.FromXmlString(privateKey);
- encryptedData = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider());
+ rsa.FromXmlString(privateKey);
+ encryptedData = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider());
#endif
- return Convert.ToBase64String(encryptedData);
- }
+ return Convert.ToBase64String(encryptedData);
}
}
}
diff --git a/src/Parbad/src/Gateway/Pasargad/Internal/PasargadHelper.cs b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadHelper.cs
index 1c766d08..7e1df4f1 100644
--- a/src/Parbad/src/Gateway/Pasargad/Internal/PasargadHelper.cs
+++ b/src/Parbad/src/Gateway/Pasargad/Internal/PasargadHelper.cs
@@ -2,264 +2,36 @@
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
-using Parbad.Abstraction;
using Parbad.Gateway.Pasargad.Internal.Models;
using Parbad.Http;
using Parbad.Internal;
-using Parbad.Options;
-using Parbad.Storage.Abstractions.Models;
-using Parbad.Utilities;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace Parbad.Gateway.Pasargad.Internal
+namespace Parbad.Gateway.Pasargad.Internal;
+
+internal static class PasargadHelper
{
- internal static class PasargadHelper
+ public static async Task BindCallbackResultModel(HttpRequest httpRequest,
+ CancellationToken cancellationToken)
{
- private const string ActionNumber = "1003";
- private const string RefundNumber = "1004";
-
- public static PaymentRequestResult CreateRequestResult(
- Invoice invoice,
- HttpContext httpContext,
- PasargadGatewayAccount account,
- IPasargadCrypto crypto,
- PasargadGatewayOptions gatewayOptions)
- {
- var invoiceDate = GetTimeStamp(DateTime.Now);
-
- var timeStamp = invoiceDate;
-
- var dataToSign = string.Format("#{0}#{1}#{2}#{3}#{4}#{5}#{6}#{7}#",
- account.MerchantCode,
- account.TerminalCode,
- invoice.TrackingNumber,
- invoiceDate,
- (long)invoice.Amount,
- invoice.CallbackUrl,
- ActionNumber,
- timeStamp);
-
- var signedData = crypto.Encrypt(account.PrivateKey, dataToSign);
-
- var result = PaymentRequestResult.SucceedWithPost(
- account.Name,
- httpContext,
- gatewayOptions.PaymentPageUrl,
- new Dictionary
- {
- {"merchantCode", account.MerchantCode},
- {"terminalCode", account.TerminalCode},
- {"invoiceNumber", invoice.TrackingNumber.ToString()},
- {"invoiceDate", invoiceDate},
- {"amount", invoice.Amount.ToLongString()},
- {"redirectAddress", invoice.CallbackUrl},
- {"action", ActionNumber},
- {"timeStamp", timeStamp},
- {"sign", signedData}
- });
-
- result.DatabaseAdditionalData.Add("timeStamp", timeStamp);
-
- return result;
- }
-
- public static async Task CreateCallbackResult(
- HttpRequest httpRequest,
- MessagesOptions messagesOptions,
- CancellationToken cancellationToken)
- {
- // Reference ID
- var invoiceNumber = await httpRequest.TryGetParamAsync("iN", cancellationToken).ConfigureAwaitFalse();
-
- // Invoice Date
- var invoiceDate = await httpRequest.TryGetParamAsync("iD", cancellationToken).ConfigureAwaitFalse();
-
- // Transaction Code
- var transactionId = await httpRequest.TryGetParamAsync("tref", cancellationToken).ConfigureAwaitFalse();
-
- var isSucceed = true;
- string message = null;
-
- if (string.IsNullOrWhiteSpace(invoiceNumber.Value) ||
- string.IsNullOrWhiteSpace(invoiceDate.Value) ||
- string.IsNullOrWhiteSpace(transactionId.Value))
- {
- isSucceed = false;
-
- message = messagesOptions.InvalidDataReceivedFromGateway;
- }
-
- var data = new[] { new KeyValuePair("invoiceUID", transactionId.Value) };
-
- return new PasargadCallbackResult
- {
- IsSucceed = isSucceed,
- InvoiceNumber = invoiceNumber.Value,
- InvoiceDate = invoiceDate.Value,
- TransactionId = transactionId.Value,
- CallbackCheckData = data,
- Message = message
- };
- }
-
- public static PasargadCheckCallbackResult CreateCheckCallbackResult(string webServiceResponse, PasargadGatewayAccount account, PasargadCallbackResult callbackResult, MessagesOptions messagesOptions)
- {
- var compareReferenceId = XmlHelper.GetNodeValueFromXml(webServiceResponse, "invoiceNumber");
- var compareAction = XmlHelper.GetNodeValueFromXml(webServiceResponse, "action");
- var compareMerchantCode = XmlHelper.GetNodeValueFromXml(webServiceResponse, "merchantCode");
- var compareTerminalCode = XmlHelper.GetNodeValueFromXml(webServiceResponse, "terminalCode");
-
- bool isSucceed;
- PaymentVerifyResult verifyResult = null;
-
- if (compareReferenceId.IsNullOrWhiteSpace() ||
- compareAction.IsNullOrWhiteSpace() ||
- compareMerchantCode.IsNullOrWhiteSpace() ||
- compareTerminalCode.IsNullOrWhiteSpace())
- {
- isSucceed = false;
-
- verifyResult = PaymentVerifyResult.Failed(messagesOptions.InvalidDataReceivedFromGateway);
- }
- else
- {
- var responseResult = XmlHelper.GetNodeValueFromXml(webServiceResponse, "result");
-
- isSucceed = responseResult.Equals("true", StringComparison.OrdinalIgnoreCase) &&
- compareReferenceId == callbackResult.InvoiceNumber &&
- compareAction == ActionNumber &&
- compareMerchantCode == account.MerchantCode &&
- compareTerminalCode == account.TerminalCode;
+ var invoiceNumber = await httpRequest.TryGetParamAsync("iN", cancellationToken).ConfigureAwaitFalse();
- if (!isSucceed)
- {
- verifyResult = PaymentVerifyResult.Failed("پرداخت موفقيت آميز نبود و يا توسط خريدار کنسل شده است");
- }
- }
+ var invoiceDate = await httpRequest.TryGetParamAsync("iD", cancellationToken).ConfigureAwaitFalse();
- return new PasargadCheckCallbackResult
- {
- IsSucceed = isSucceed,
- Result = verifyResult
- };
- }
+ var transactionReferenceId = await httpRequest.TryGetParamAsync("tref", cancellationToken).ConfigureAwaitFalse();
- public static IEnumerable> CreateVerifyData(
- InvoiceContext context,
- PasargadGatewayAccount account,
- IPasargadCrypto crypto,
- PasargadCallbackResult callbackResult)
- {
- var timeStamp = GetTimeStamp(DateTime.Now);
-
- var dataToSign = string.Format("#{0}#{1}#{2}#{3}#{4}#{5}#",
- account.MerchantCode,
- account.TerminalCode,
- context.Payment.TrackingNumber,
- callbackResult.InvoiceDate,
- (long)context.Payment.Amount,
- timeStamp);
-
- var signData = crypto.Encrypt(account.PrivateKey, dataToSign);
-
- return new[]
- {
- new KeyValuePair("InvoiceNumber", context.Payment.TrackingNumber.ToString()),
- new KeyValuePair("InvoiceDate", callbackResult.InvoiceDate),
- new KeyValuePair("MerchantCode", account.MerchantCode),
- new KeyValuePair("TerminalCode", account.TerminalCode),
- new KeyValuePair("Amount", ((long)context.Payment.Amount).ToString()),
- new KeyValuePair("TimeStamp", timeStamp),
- new KeyValuePair("Sign", signData)
- };
- }
-
- public static PaymentVerifyResult CreateVerifyResult(string webServiceResponse, PasargadCallbackResult callbackResult, MessagesOptions messagesOptions)
- {
- var result = XmlHelper.GetNodeValueFromXml(webServiceResponse, "result");
-
- var isSucceed = result.Equals("true", StringComparison.OrdinalIgnoreCase);
-
- var message = isSucceed
- ? messagesOptions.PaymentSucceed
- : XmlHelper.GetNodeValueFromXml(webServiceResponse, "resultMessage");
-
- return new PaymentVerifyResult
- {
- Status = isSucceed ? PaymentVerifyResultStatus.Succeed : PaymentVerifyResultStatus.Failed,
- TransactionCode = callbackResult.TransactionId,
- Message = message
- };
- }
-
- public static IEnumerable> CreateRefundData(
- InvoiceContext context,
- Money amount,
- IPasargadCrypto crypto,
- PasargadGatewayAccount account)
- {
- var transactionRecord = context.Transactions.FirstOrDefault(transaction => transaction.Type == TransactionType.Request);
-
- if (transactionRecord == null)
- {
- throw new Exception($"Cannot find transaction record for Payment-{context.Payment.TrackingNumber}");
- }
-
- if (!AdditionalDataConverter.ToDictionary(transactionRecord).TryGetValue("invoiceDate", out var invoiceDate))
- {
- throw new Exception("Cannot get the invoiceDate from database.");
- }
-
- var timeStamp = GetTimeStamp(DateTime.Now);
-
- var dataToSign = string.Format("#{0}#{1}#{2}#{3}#{4}#{5}#{6}#",
- account.MerchantCode,
- account.TerminalCode,
- context.Payment.TrackingNumber,
- invoiceDate,
- (long)amount,
- RefundNumber,
- timeStamp);
-
- var signedData = crypto.Encrypt(account.PrivateKey, dataToSign);
-
- return new[]
- {
- new KeyValuePair("InvoiceNumber", context.Payment.TrackingNumber.ToString()),
- new KeyValuePair("InvoiceDate", invoiceDate),
- new KeyValuePair("MerchantCode", account.MerchantCode),
- new KeyValuePair("TerminalCode", account.TerminalCode),
- new KeyValuePair("Amount", amount.ToLongString()),
- new KeyValuePair("action", RefundNumber),
- new KeyValuePair("TimeStamp", timeStamp),
- new KeyValuePair("Sign", signedData)
- };
- }
-
- public static PaymentRefundResult CreateRefundResult(string webServiceResponse, MessagesOptions messagesOptions)
- {
- var result = XmlHelper.GetNodeValueFromXml(webServiceResponse, "result");
-
- var isSucceed = result.Equals("true", StringComparison.OrdinalIgnoreCase);
-
- var message = isSucceed
- ? messagesOptions.PaymentSucceed
- : XmlHelper.GetNodeValueFromXml(webServiceResponse, "resultMessage");
-
- return new PaymentRefundResult
- {
- Status = isSucceed ? PaymentRefundResultStatus.Succeed : PaymentRefundResultStatus.Failed,
- Message = message
- };
- }
+ return new PasargadCallbackResultModel
+ {
+ InvoiceNumber = invoiceNumber.Value,
+ InvoiceDate = invoiceDate.Value,
+ TransactionReferenceId = transactionReferenceId.Value
+ };
+ }
- private static string GetTimeStamp(DateTime dateTime)
- {
- return dateTime.ToString("yyyy/MM/dd HH:mm:ss");
- }
+ public static string GetTimeStamp()
+ {
+ return DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
}
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadGateway.cs b/src/Parbad/src/Gateway/Pasargad/PasargadGateway.cs
index c122e1ea..13ab0034 100644
--- a/src/Parbad/src/Gateway/Pasargad/PasargadGateway.cs
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadGateway.cs
@@ -7,138 +7,188 @@
using Parbad.Gateway.Pasargad.Internal;
using Parbad.GatewayBuilders;
using Parbad.Internal;
-using Parbad.Net;
using Parbad.Options;
using System;
-using System.Net.Http;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Parbad.Gateway.Pasargad.Api;
+using Parbad.Gateway.Pasargad.Api.Models;
+using Parbad.Storage.Abstractions.Models;
-namespace Parbad.Gateway.Pasargad
+namespace Parbad.Gateway.Pasargad;
+
+[Gateway(Name)]
+public class PasargadGateway : GatewayBase
{
- [Gateway(Name)]
- public class PasargadGateway : GatewayBase
+ private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly IPasargadApi _pasargadApi;
+ private readonly PasargadGatewayOptions _gatewayOptions;
+ private readonly MessagesOptions _messageOptions;
+
+ private const string InvoiceDateKey = "invoiceDate";
+ public const string Name = "Pasargad";
+
+ public PasargadGateway(IHttpContextAccessor httpContextAccessor,
+ IPasargadApi pasargadApi,
+ IGatewayAccountProvider accountProvider,
+ IOptions gatewayOptions,
+ IOptions messageOptions)
+ : base(accountProvider)
{
- private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly HttpClient _httpClient;
- private readonly IPasargadCrypto _crypto;
- private readonly PasargadGatewayOptions _gatewayOptions;
- private readonly IOptions _messageOptions;
-
- public const string Name = "Pasargad";
-
- public PasargadGateway(
- IHttpContextAccessor httpContextAccessor,
- IHttpClientFactory httpClientFactory,
- IGatewayAccountProvider accountProvider,
- IPasargadCrypto crypto,
- IOptions gatewayOptions,
- IOptions messageOptions) : base(accountProvider)
- {
- _httpContextAccessor = httpContextAccessor;
- _httpClient = httpClientFactory.CreateClient(this);
- _crypto = crypto;
- _gatewayOptions = gatewayOptions.Value;
- _messageOptions = messageOptions;
- }
+ _httpContextAccessor = httpContextAccessor;
+ _pasargadApi = pasargadApi;
+ _gatewayOptions = gatewayOptions.Value;
+ _messageOptions = messageOptions.Value;
+ }
- ///
- public override async Task RequestAsync(Invoice invoice, CancellationToken cancellationToken = default)
+ ///
+ public override async Task RequestAsync(Invoice invoice, CancellationToken cancellationToken = default)
+ {
+ if (invoice == null) throw new ArgumentNullException(nameof(invoice));
+
+ var account = await GetAccountAsync(invoice).ConfigureAwaitFalse();
+
+ var invoiceDate = PasargadHelper.GetTimeStamp();
+ var timeStamp = invoiceDate;
+
+ var additionalData = invoice.GetPasargadRequestAdditionalData();
+
+ var response = await _pasargadApi.GetToken(new PasargadGetTokenRequestModel
+ {
+ MerchantCode = account.MerchantCode,
+ TerminalCode = account.TerminalCode,
+ InvoiceNumber = invoice.TrackingNumber.ToString(),
+ InvoiceDate = invoiceDate,
+ Amount = invoice.Amount,
+ RedirectAddress = invoice.CallbackUrl,
+ Timestamp = timeStamp,
+ Email = additionalData?.Email,
+ Mobile = additionalData?.Mobile,
+ Pidn = additionalData?.Pidn,
+ MerchantName = additionalData?.MerchantName
+ },
+ account.PrivateKey,
+ cancellationToken)
+ .ConfigureAwaitFalse();
+
+ if (!response.IsSuccess)
{
- if (invoice == null) throw new ArgumentNullException(nameof(invoice));
+ return PaymentRequestResult.Failed(response.Message, account.Name);
+ }
- var account = await GetAccountAsync(invoice).ConfigureAwaitFalse();
+ var form = new Dictionary
+ {
+ { "Token", response.Token }
+ };
- return PasargadHelper.CreateRequestResult(invoice, _httpContextAccessor.HttpContext, account, _crypto, _gatewayOptions);
- }
+ var result = PaymentRequestResult.SucceedWithPost(account.Name,
+ _httpContextAccessor.HttpContext,
+ _gatewayOptions.PaymentPageUrl,
+ form);
- ///
- public override async Task FetchAsync(InvoiceContext context, CancellationToken cancellationToken = default)
- {
- if (context == null) throw new ArgumentNullException(nameof(context));
+ result.DatabaseAdditionalData.Add(InvoiceDateKey, invoiceDate);
- var callbackResult = await PasargadHelper.CreateCallbackResult(
- _httpContextAccessor.HttpContext.Request,
- _messageOptions.Value,
- cancellationToken)
- .ConfigureAwaitFalse();
+ return result;
+ }
- if (callbackResult.IsSucceed)
- {
- return PaymentFetchResult.ReadyForVerifying();
- }
+ ///
+ public override async Task FetchAsync(InvoiceContext context, CancellationToken cancellationToken = default)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
- return PaymentFetchResult.Failed(callbackResult.Message);
- }
+ var callbackResult = await PasargadHelper.BindCallbackResultModel(_httpContextAccessor.HttpContext.Request,
+ cancellationToken)
+ .ConfigureAwaitFalse();
- ///
- public override async Task VerifyAsync(InvoiceContext context, CancellationToken cancellationToken = default)
+ if (!callbackResult.IsSucceed)
{
- if (context == null) throw new ArgumentNullException(nameof(context));
-
- var callbackResult = await PasargadHelper.CreateCallbackResult(
- _httpContextAccessor.HttpContext.Request,
- _messageOptions.Value,
- cancellationToken)
- .ConfigureAwaitFalse();
+ return PaymentFetchResult.Failed(_messageOptions.PaymentFailed);
+ }
- if (!callbackResult.IsSucceed)
- {
- return PaymentVerifyResult.Failed(callbackResult.Message);
- }
+ var result = PaymentFetchResult.ReadyForVerifying();
+ result.TransactionCode = callbackResult.TransactionReferenceId;
- var responseMessage = await _httpClient.PostFormAsync(
- _gatewayOptions.ApiCheckPaymentUrl,
- callbackResult.CallbackCheckData,
- cancellationToken)
- .ConfigureAwaitFalse();
+ return result;
+ }
- var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwaitFalse();
+ ///
+ public override async Task VerifyAsync(InvoiceContext context, CancellationToken cancellationToken = default)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
- var account = await GetAccountAsync(context.Payment).ConfigureAwaitFalse();
+ var callbackResult = await PasargadHelper.BindCallbackResultModel(_httpContextAccessor.HttpContext.Request,
+ cancellationToken)
+ .ConfigureAwaitFalse();
- var checkCallbackResult = PasargadHelper.CreateCheckCallbackResult(
- response,
- account,
- callbackResult,
- _messageOptions.Value);
+ if (!callbackResult.IsSucceed)
+ {
+ return PaymentVerifyResult.Failed(_messageOptions.PaymentFailed);
+ }
- if (!checkCallbackResult.IsSucceed)
- {
- return checkCallbackResult.Result;
- }
+ var account = await GetAccountAsync(context.Payment).ConfigureAwaitFalse();
+
+ var response = await _pasargadApi.VerifyPayment(new PasargadVerifyPaymentRequestModel
+ {
+ MerchantCode = account.MerchantCode,
+ TerminalCode = account.TerminalCode,
+ InvoiceNumber = context.Payment.TrackingNumber.ToString(),
+ InvoiceDate = callbackResult.InvoiceDate,
+ Amount = context.Payment.Amount,
+ Timestamp = PasargadHelper.GetTimeStamp()
+ },
+ account.PrivateKey,
+ cancellationToken)
+ .ConfigureAwaitFalse();
+
+ if (!response.IsSuccess)
+ {
+ return PaymentVerifyResult.Failed(response.Message ?? _messageOptions.PaymentFailed);
+ }
- var data = PasargadHelper.CreateVerifyData(context, account, _crypto, callbackResult);
+ return PaymentVerifyResult.Succeed(callbackResult.TransactionReferenceId,
+ _messageOptions.PaymentSucceed);
+ }
- responseMessage = await _httpClient.PostFormAsync(
- _gatewayOptions.ApiVerificationUrl,
- data,
- cancellationToken)
- .ConfigureAwaitFalse();
+ ///
+ public override async Task RefundAsync(InvoiceContext context, Money amount, CancellationToken cancellationToken = default)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
- response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwaitFalse();
+ var account = await GetAccountAsync(context.Payment).ConfigureAwaitFalse();
- return PasargadHelper.CreateVerifyResult(response, callbackResult, _messageOptions.Value);
- }
+ var requestTransaction = context.Transactions.SingleOrDefault(transaction => transaction.Type == TransactionType.Request);
- ///
- public override async Task RefundAsync(InvoiceContext context, Money amount, CancellationToken cancellationToken = default)
+ if (requestTransaction == null)
{
- if (context == null) throw new ArgumentNullException(nameof(context));
-
- var account = await GetAccountAsync(context.Payment).ConfigureAwaitFalse();
-
- var data = PasargadHelper.CreateRefundData(context, amount, _crypto, account);
+ return PaymentRefundResult.Failed($"Transaction for Invoice {context.Payment.TrackingNumber} not found");
+ }
- var responseMessage = await _httpClient.PostFormAsync(
- _gatewayOptions.ApiRefundUrl,
- data,
- cancellationToken)
- .ConfigureAwaitFalse();
+ var requestTransactionAdditionalData = requestTransaction.ToDictionary();
- var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwaitFalse();
+ if (!requestTransactionAdditionalData.TryGetValue(InvoiceDateKey, out var invoiceDate))
+ {
+ return PaymentRefundResult.Failed($"InvoiceDate for Invoice {context.Payment.TrackingNumber} not found");
+ }
- return PasargadHelper.CreateRefundResult(response, _messageOptions.Value);
+ var response = await _pasargadApi.RefundPayment(new PasargadRefundPaymentRequestModel
+ {
+ MerchantCode = account.MerchantCode,
+ TerminalCode = account.TerminalCode,
+ InvoiceNumber = context.Payment.TrackingNumber.ToString(),
+ InvoiceDate = invoiceDate,
+ Timestamp = PasargadHelper.GetTimeStamp()
+ },
+ account.PrivateKey,
+ cancellationToken)
+ .ConfigureAwaitFalse();
+
+ if (!response.IsSuccess)
+ {
+ return PaymentRefundResult.Failed(response.Message ?? "Refund failed.");
}
+
+ return PaymentRefundResult.Succeed();
}
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayAccount.cs b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayAccount.cs
index 5dbf52cf..be75398c 100644
--- a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayAccount.cs
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayAccount.cs
@@ -3,14 +3,13 @@
using Parbad.Abstraction;
-namespace Parbad.Gateway.Pasargad
+namespace Parbad.Gateway.Pasargad;
+
+public class PasargadGatewayAccount : GatewayAccount
{
- public class PasargadGatewayAccount : GatewayAccount
- {
- public string MerchantCode { get; set; }
+ public string MerchantCode { get; set; }
- public string TerminalCode { get; set; }
+ public string TerminalCode { get; set; }
- public string PrivateKey { get; set; }
- }
+ public string PrivateKey { get; set; }
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayBuilderExtensions.cs b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayBuilderExtensions.cs
index 5205f149..d9051b88 100644
--- a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayBuilderExtensions.cs
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayBuilderExtensions.cs
@@ -2,56 +2,117 @@
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
using System;
+using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Parbad.Gateway.Pasargad.Api;
using Parbad.Gateway.Pasargad.Internal;
using Parbad.GatewayBuilders;
-namespace Parbad.Gateway.Pasargad
+namespace Parbad.Gateway.Pasargad;
+
+public static class PasargadGatewayBuilderExtensions
{
- public static class PasargadGatewayBuilderExtensions
+ ///
+ /// Adds Pasargad gateway to Parbad services.
+ ///
+ ///
+ public static IGatewayConfigurationBuilder AddPasargad(this IGatewayBuilder builder)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+
+ return builder
+ .AddGateway()
+ .WithHttpClient((serviceProvider, httpClient) =>
+ {
+ var gatewayOptions = serviceProvider.GetRequiredService>();
+
+ httpClient.BaseAddress = new Uri(gatewayOptions.Value.ApiBaseUrl);
+ })
+ .WithEncryptor(ServiceLifetime.Transient)
+ .WithOptions(options => { });
+ }
+
+ ///
+ /// Configures the HttpClient for .
+ ///
+ /// Implementation type of .
+ ///
+ public static IGatewayConfigurationBuilder WithHttpClient(this IGatewayConfigurationBuilder builder,
+ Action configureHttpClient,
+ Action configureHttpClientBuilder = null)
+ where TGatewayApi : class, IPasargadApi
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (configureHttpClient == null) throw new ArgumentNullException(nameof(configureHttpClient));
+
+ builder.WithHttpClient(configureHttpClient, configureHttpClientBuilder);
+
+ return builder;
+ }
+
+ ///
+ /// Configures the accounts for .
+ ///
+ ///
+ /// Configures the accounts.
+ public static IGatewayConfigurationBuilder WithAccounts(
+ this IGatewayConfigurationBuilder builder,
+ Action> configureAccounts)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+
+ return builder.WithAccounts(configureAccounts);
+ }
+
+ ///
+ /// Configures the options for Pasargad Gateway.
+ ///
+ ///
+ /// Configuration
+ public static IGatewayConfigurationBuilder WithOptions(
+ this IGatewayConfigurationBuilder builder,
+ Action configureOptions)
+ {
+ builder.Services.Configure(configureOptions);
+
+ return builder;
+ }
+
+ ///
+ /// Registers an Encryptor for .
+ ///
+ public static IGatewayConfigurationBuilder WithEncryptor(
+ this IGatewayConfigurationBuilder builder,
+ IPasargadCrypto crypto)
+ {
+ builder.Services.AddOrUpdate(crypto);
+
+ return builder;
+ }
+
+ ///
+ /// Registers an Encryptor for .
+ ///
+ public static IGatewayConfigurationBuilder WithEncryptor(
+ this IGatewayConfigurationBuilder builder,
+ ServiceLifetime lifetime)
+ where TEncryptor : class, IPasargadCrypto
{
- ///
- /// Adds Pasargad gateway to Parbad services.
- ///
- ///
- public static IGatewayConfigurationBuilder AddPasargad(this IGatewayBuilder builder)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
-
- builder.Services.AddSingleton();
-
- return builder
- .AddGateway()
- .WithHttpClient(clientBuilder => { })
- .WithOptions(options => { });
- }
-
- ///
- /// Configures the accounts for .
- ///
- ///
- /// Configures the accounts.
- public static IGatewayConfigurationBuilder WithAccounts(
- this IGatewayConfigurationBuilder builder,
- Action> configureAccounts)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
-
- return builder.WithAccounts(configureAccounts);
- }
-
- ///
- /// Configures the options for Pasargad Gateway.
- ///
- ///
- /// Configuration
- public static IGatewayConfigurationBuilder WithOptions(
- this IGatewayConfigurationBuilder builder,
- Action configureOptions)
- {
- builder.Services.Configure(configureOptions);
-
- return builder;
- }
+ builder.Services.AddOrUpdate(lifetime);
+
+ return builder;
+ }
+
+ ///
+ /// Registers an Encryptor for .
+ ///
+ public static IGatewayConfigurationBuilder WithEncryptor(
+ this IGatewayConfigurationBuilder builder,
+ Func setup)
+ {
+ builder.Services.AddOrUpdate(setup);
+
+ return builder;
}
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayInvoiceBuilderExtensions.cs b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayInvoiceBuilderExtensions.cs
index 746d6bdf..a9fea50e 100644
--- a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayInvoiceBuilderExtensions.cs
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayInvoiceBuilderExtensions.cs
@@ -1,19 +1,48 @@
-using System;
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+using System;
+using Parbad.Abstraction;
using Parbad.InvoiceBuilder;
-namespace Parbad.Gateway.Pasargad
+namespace Parbad.Gateway.Pasargad;
+
+public static class PasargadGatewayInvoiceBuilderExtensions
{
- public static class PasargadGatewayInvoiceBuilderExtensions
+ private const string RequestAdditionalDataKey = nameof(RequestAdditionalDataKey);
+
+ ///
+ /// The invoice will be sent to Pasargad gateway.
+ ///
+ ///
+ public static IInvoiceBuilder UsePasargad(this IInvoiceBuilder builder)
{
- ///
- /// The invoice will be sent to Pasargad gateway.
- ///
- ///
- public static IInvoiceBuilder UsePasargad(this IInvoiceBuilder builder)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+
+ return builder.SetGateway(PasargadGateway.Name);
+ }
+
+ ///
+ /// Sets additional data that will be sent to Pasargad gateway when requesting a token.
+ ///
+ ///
+ public static IInvoiceBuilder SetPasargadData(this IInvoiceBuilder builder, PasargadRequestAdditionalData additionalData)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (additionalData == null) throw new ArgumentNullException(nameof(additionalData));
+
+ return builder.AddOrUpdateProperty(RequestAdditionalDataKey, additionalData);
+ }
- return builder.SetGateway(PasargadGateway.Name);
+ internal static PasargadRequestAdditionalData GetPasargadRequestAdditionalData(this Invoice invoice)
+ {
+ if (invoice == null) throw new ArgumentNullException(nameof(invoice));
+
+ if (!invoice.Properties.TryGetValue(RequestAdditionalDataKey, out var additionalData))
+ {
+ return null;
}
+
+ return (PasargadRequestAdditionalData)additionalData;
}
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayOptions.cs b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayOptions.cs
index e0197bcf..fbcd6f2a 100644
--- a/src/Parbad/src/Gateway/Pasargad/PasargadGatewayOptions.cs
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadGatewayOptions.cs
@@ -1,13 +1,17 @@
-namespace Parbad.Gateway.Pasargad
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad;
+
+public class PasargadGatewayOptions
{
- public class PasargadGatewayOptions
- {
- public string PaymentPageUrl { get; set; } = "https://pep.shaparak.ir/gateway.aspx";
+ public string PaymentPageUrl { get; set; } = "https://pep.shaparak.ir/payment.aspx";
+
+ public string ApiBaseUrl { get; set; } = "https://pep.shaparak.ir/Api/v1/";
- public string ApiCheckPaymentUrl { get; set; } = "https://pep.shaparak.ir/CheckTransactionResult.aspx";
+ public string ApiGetTokenUrl { get; set; } = "Payment/GetToken";
- public string ApiVerificationUrl { get; set; } = "https://pep.shaparak.ir/VerifyPayment.aspx";
+ public string ApiVerificationUrl { get; set; } = "Payment/VerifyPayment";
- public string ApiRefundUrl { get; set; } = "https://pep.shaparak.ir/DoRefund.aspx";
- }
+ public string ApiRefundUrl { get; set; } = "Payment/RefundPayment";
}
diff --git a/src/Parbad/src/Gateway/Pasargad/PasargadRequestAdditionalData.cs b/src/Parbad/src/Gateway/Pasargad/PasargadRequestAdditionalData.cs
new file mode 100644
index 00000000..5dd31a7e
--- /dev/null
+++ b/src/Parbad/src/Gateway/Pasargad/PasargadRequestAdditionalData.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Parbad. All rights reserved.
+// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+
+namespace Parbad.Gateway.Pasargad;
+
+///
+/// Additional Data that can be sent to Pasargad gateway when requesting a token.
+///
+public class PasargadRequestAdditionalData
+{
+ public string Mobile { get; set; }
+
+ public string Email { get; set; }
+
+ public string MerchantName { get; set; }
+
+ public string Pidn { get; set; }
+}
diff --git a/src/Parbad/src/Gateway/Saman/Internal/Models/SamanTokenRequest.cs b/src/Parbad/src/Gateway/Saman/Internal/Models/SamanTokenRequest.cs
index 086e5ad5..63ca1fa7 100644
--- a/src/Parbad/src/Gateway/Saman/Internal/Models/SamanTokenRequest.cs
+++ b/src/Parbad/src/Gateway/Saman/Internal/Models/SamanTokenRequest.cs
@@ -16,7 +16,7 @@ internal class SamanTokenRequest
public string ResNum { get; set; }
- public CallbackUrl RedirectUrl { get; set; }
+ public string RedirectUrl { get; set; }
public string CellNumber { get; set; }
}
diff --git a/src/Parbad/src/Gateway/Saman/Internal/SamanHelper.cs b/src/Parbad/src/Gateway/Saman/Internal/SamanHelper.cs
index 2f6f3ee6..105a29df 100644
--- a/src/Parbad/src/Gateway/Saman/Internal/SamanHelper.cs
+++ b/src/Parbad/src/Gateway/Saman/Internal/SamanHelper.cs
@@ -21,6 +21,8 @@ namespace Parbad.Gateway.Saman.Internal;
internal static class SamanHelper
{
private const string RefNumKey = nameof(RefNumKey);
+ private const string CallbackSuccessCode = "2";
+ private const int VerificationSuccessCode = 0;
public const string AdditionalVerificationDataKey = "SamanAdditionalVerificationData";
public const string CellNumberPropertyKey = "SamanCellNumber";
@@ -98,40 +100,6 @@ public static async Task BindCallbackResponse(HttpRequest
SecurePan = securePan.Value,
HashedCardNumber = hashedCardNumber.Value,
};
-
- // var status = await httpRequest.TryGetParamAsync("status", cancellationToken).ConfigureAwaitFalse();
- //
- // if (!status.Exists || status.Value.IsNullOrEmpty())
- // {
- // message = messagesOptions.InvalidDataReceivedFromGateway;
- // }
- // else
- // {
- // var referenceIdResult = await httpRequest.TryGetParamAsync("ResNum", cancellationToken).ConfigureAwaitFalse();
- // if (referenceIdResult.Exists) referenceId = referenceIdResult.Value;
- //
- // var transactionIdResult = await httpRequest.TryGetParamAsync("RefNum", cancellationToken).ConfigureAwaitFalse();
- // if (transactionIdResult.Exists) transactionId = transactionIdResult.Value;
- //
- // isSuccess = status.Value.Equals("OK", StringComparison.OrdinalIgnoreCase);
- //
- // if (!isSuccess)
- // {
- // message = SamanStateTranslator.Translate(status.Value, messagesOptions);
- // }
- // }
- //
- // return new SamanCallbackResult
- // {
- // IsSucceed = isSuccess,
- // ReferenceId = referenceId,
- // TransactionId = transactionId,
- // SecurePan = securePan.Value,
- // Cid = cid.Value,
- // TraceNo = traceNo.Value,
- // Rrn = rrn.Value,
- // Message = message
- // };
}
public static IPaymentFetchResult CreateFetchResult(SamanCallbackResponse callbackResponse,
@@ -141,7 +109,7 @@ public static IPaymentFetchResult CreateFetchResult(SamanCallbackResponse callba
{
var isCallbackResponseValid = ValidateCallbackResponse(callbackResponse, invoiceContext, gatewayAccount, out var message);
- var isReceivedSuccessFromGateway = callbackResponse.Status == "2";
+ var isReceivedSuccessFromGateway = callbackResponse.Status == CallbackSuccessCode;
var isSucceed = isCallbackResponseValid && isReceivedSuccessFromGateway;
@@ -184,9 +152,9 @@ public static PaymentVerifyResult CreateVerifyResult(SamanGatewayAccount gateway
{
var isSuccess = verificationResponse.TransactionDetail.TerminalNumber.ToString() == gatewayAccount.TerminalId &&
verificationResponse.TransactionDetail.AffectiveAmount == (long)invoiceContext.Payment.Amount &&
- verificationResponse.TransactionDetail.RefNum == callbackResponse.RefNum;
-
-
+ verificationResponse.TransactionDetail.RefNum == callbackResponse.RefNum &&
+ verificationResponse.ResultCode == VerificationSuccessCode;
+
var message = isSuccess
? messagesOptions.PaymentSucceed
: SamanResultTranslator.Translate(verificationResponse.ResultCode.ToString(), messagesOptions);
@@ -213,7 +181,8 @@ public static SamanReverseRequest CreateReverseRequest(InvoiceContext context, S
if (string.IsNullOrEmpty(verificationTransaction?.AdditionalData) ||
!verificationTransaction.ToDictionary().ContainsKey(RefNumKey))
{
- throw new InvalidOperationException($"No Transaction of type Verification or additional data found for reversing the invoice {context.Payment.TrackingNumber}.");
+ throw new
+ InvalidOperationException($"No Transaction of type Verification or additional data found for reversing the invoice {context.Payment.TrackingNumber}.");
}
return new()
diff --git a/src/Parbad/src/GatewayBuilders/IGatewayBuilder.cs b/src/Parbad/src/GatewayBuilders/IGatewayBuilder.cs
index fa43551d..f68fedfa 100644
--- a/src/Parbad/src/GatewayBuilders/IGatewayBuilder.cs
+++ b/src/Parbad/src/GatewayBuilders/IGatewayBuilder.cs
@@ -4,25 +4,24 @@
using Microsoft.Extensions.DependencyInjection;
using Parbad.Abstraction;
-namespace Parbad.GatewayBuilders
+namespace Parbad.GatewayBuilders;
+
+///
+/// A builder for building a gateway.
+///
+public interface IGatewayBuilder
{
///
- /// A builder for building a gateway.
+ /// Specifies the contract for a collection of service descriptors.
///
- public interface IGatewayBuilder
- {
- ///
- /// Specifies the contract for a collection of service descriptors.
- ///
- IServiceCollection Services { get; }
+ IServiceCollection Services { get; }
- ///
- /// Adds the specified gateway to Parbad services.
- ///
- /// Type of gateway.
- /// Lifetime of .
- IGatewayConfigurationBuilder AddGateway(
- ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
- where TGateway : class, IGateway;
- }
+ ///
+ /// Adds the specified gateway to Parbad services.
+ ///
+ /// Type of gateway.
+ /// Lifetime of .
+ IGatewayConfigurationBuilder AddGateway(
+ ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
+ where TGateway : class, IGateway;
}
diff --git a/src/Parbad/src/GatewayBuilders/IGatewayConfigurationBuilder.cs b/src/Parbad/src/GatewayBuilders/IGatewayConfigurationBuilder.cs
index 904f2670..b470f92d 100644
--- a/src/Parbad/src/GatewayBuilders/IGatewayConfigurationBuilder.cs
+++ b/src/Parbad/src/GatewayBuilders/IGatewayConfigurationBuilder.cs
@@ -6,33 +6,40 @@
using Microsoft.Extensions.DependencyInjection;
using Parbad.Abstraction;
-namespace Parbad.GatewayBuilders
+namespace Parbad.GatewayBuilders;
+
+///
+/// A builder for configuring the specified gateway.
+///
+/// Type of gateway.
+public interface IGatewayConfigurationBuilder where TGateway : class, IGateway
{
///
- /// A builder for configuring the specified gateway.
+ /// Specifies the contract for a collection of service descriptors.
+ ///
+ IServiceCollection Services { get; }
+
+ ///
+ /// Configures the accounts of type for .
///
- /// Type of gateway.
- public interface IGatewayConfigurationBuilder where TGateway : class, IGateway
- {
- ///
- /// Specifies the contract for a collection of service descriptors.
- ///
- IServiceCollection Services { get; }
+ /// Account of .
+ /// Configures the accounts.
+ IGatewayConfigurationBuilder WithAccounts(
+ Action> configureAccounts)
+ where TAccount : GatewayAccount, new();
- ///
- /// Configures the accounts of type for .
- ///
- /// Account of .
- /// Configures the accounts.
- IGatewayConfigurationBuilder WithAccounts(
- Action> configureAccounts)
- where TAccount : GatewayAccount, new();
+ ///
+ /// Configures the required by
+ /// for sending HTTP requests and receiving HTTP responses.
+ ///
+ /// HttpClient configuration.
+ IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient);
- ///
- /// Configures the required by
- /// for sending HTTP requests and receiving HTTP responses.
- ///
- /// HttpClient configuration.
- IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient);
- }
+ ///
+ /// Configures the HttpClient for TGateway and its implementation.
+ ///
+ IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient,
+ Action configureHttpClientBuilder = null)
+ where TGatewayApi : class
+ where TGatewayApiImplementation : class, TGatewayApi;
}
diff --git a/src/Parbad/src/Internal/GatewayBuilder.cs b/src/Parbad/src/Internal/GatewayBuilder.cs
index ea8df9cd..2d2cfc0e 100644
--- a/src/Parbad/src/Internal/GatewayBuilder.cs
+++ b/src/Parbad/src/Internal/GatewayBuilder.cs
@@ -5,33 +5,32 @@
using Parbad.Abstraction;
using Parbad.GatewayBuilders;
-namespace Parbad.Internal
+namespace Parbad.Internal;
+
+///
+internal class GatewayBuilder : IGatewayBuilder
{
- ///
- internal class GatewayBuilder : IGatewayBuilder
+ ///
+ /// Initializes an instance of .
+ ///
+ ///
+ public GatewayBuilder(IServiceCollection services)
{
- ///
- /// Initializes an instance of .
- ///
- ///
- public GatewayBuilder(IServiceCollection services)
- {
- Services = services;
- }
+ Services = services;
+ }
- ///
- public IServiceCollection Services { get; }
+ ///
+ public IServiceCollection Services { get; }
- ///
- public IGatewayConfigurationBuilder AddGateway(
- ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
- where TGateway : class, IGateway
- {
- Services.AddSingleton(new GatewayDescriptor(typeof(TGateway)));
+ ///
+ public IGatewayConfigurationBuilder AddGateway(
+ ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
+ where TGateway : class, IGateway
+ {
+ Services.AddSingleton(new GatewayDescriptor(typeof(TGateway)));
- Services.TryAdd(serviceLifetime);
+ Services.TryAdd(serviceLifetime);
- return new GatewayConfigurationBuilder(Services);
- }
+ return new GatewayConfigurationBuilder(Services);
}
}
diff --git a/src/Parbad/src/Internal/GatewayConfigurationBuilder.cs b/src/Parbad/src/Internal/GatewayConfigurationBuilder.cs
index 605ca1c6..d040575d 100644
--- a/src/Parbad/src/Internal/GatewayConfigurationBuilder.cs
+++ b/src/Parbad/src/Internal/GatewayConfigurationBuilder.cs
@@ -2,48 +2,70 @@
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
using System;
+using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Parbad.Abstraction;
using Parbad.GatewayBuilders;
using Parbad.Net;
-namespace Parbad.Internal
+namespace Parbad.Internal;
+
+///
+internal class GatewayConfigurationBuilder : IGatewayConfigurationBuilder
+ where TGateway : class, IGateway
{
- internal class GatewayConfigurationBuilder : IGatewayConfigurationBuilder
- where TGateway : class, IGateway
+ public GatewayConfigurationBuilder(IServiceCollection services)
{
- public GatewayConfigurationBuilder(IServiceCollection services)
- {
- Services = services;
- }
+ Services = services;
+ }
- public IServiceCollection Services { get; }
+ ///
+ public IServiceCollection Services { get; }
- public IGatewayConfigurationBuilder WithAccounts(Action> configureAccounts)
- where TAccount : GatewayAccount, new()
- {
- if (configureAccounts == null) throw new ArgumentNullException(nameof(configureAccounts));
+ ///
+ public IGatewayConfigurationBuilder WithAccounts(Action> configureAccounts)
+ where TAccount : GatewayAccount, new()
+ {
+ if (configureAccounts == null) throw new ArgumentNullException(nameof(configureAccounts));
- configureAccounts(new GatewayAccountBuilder(Services));
+ configureAccounts(new GatewayAccountBuilder(Services));
- Services
- .TryAddTransient<
- IGatewayAccountProvider,
- GatewayAccountProvider>();
+ Services
+ .TryAddTransient<
+ IGatewayAccountProvider,
+ GatewayAccountProvider>();
- return this;
- }
+ return this;
+ }
- public IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient)
- {
- if (configureHttpClient == null) throw new ArgumentNullException(nameof(configureHttpClient));
+ ///
+ public IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient)
+ {
+ if (configureHttpClient == null) throw new ArgumentNullException(nameof(configureHttpClient));
+
+ var httpClientBuilder = Services.AddHttpClientForGateway();
+
+ configureHttpClient(httpClientBuilder);
+
+ return this;
+ }
- var httpClientBuilder = Services.AddHttpClientForGateway();
+ ///
+ public IGatewayConfigurationBuilder WithHttpClient(Action configureHttpClient,
+ Action configureHttpClientBuilder = null)
+ where TGatewayApi : class
+ where TGatewayApiImplementation : class, TGatewayApi
+ {
+ if (configureHttpClient == null) throw new ArgumentNullException(nameof(configureHttpClient));
- configureHttpClient(httpClientBuilder);
+ var httpClientBuilder = Services.AddHttpClient(configureHttpClient);
- return this;
+ if (configureHttpClientBuilder != null)
+ {
+ configureHttpClientBuilder(httpClientBuilder);
}
+
+ return this;
}
}
diff --git a/src/Parbad/src/Parbad.csproj b/src/Parbad/src/Parbad.csproj
index 892c3a12..8100abd6 100644
--- a/src/Parbad/src/Parbad.csproj
+++ b/src/Parbad/src/Parbad.csproj
@@ -3,8 +3,8 @@
Parbad
Parbad
- 3.9.2
- netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0
+ 3.10.0
+ netstandard2.0;netstandard2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0
latest
Parbad Sina Soltani
Parbad is a free, open-source, integrated and extensible library which connects your web applications to online payment gateways. Gateways can be added or developed by you.
@@ -23,7 +23,7 @@ More information: https://github.com/Sina-Soltani/Parbad
true
parbad Payment Gateway virtual virtual-gateway Bank Iran Shetab IranKish Mellat Melli Sadad Parsian Pasargad Saman Asan-Pardakht پرداخت درگاه بانک ایران شتاب ایران-کیش ملت ملی سداد پارسیان پاسارگاد سامان آسان-پرداخت
true
- https://github.com/Sina-Soltani/Parbad/releases/tag/v3.9.2
+ https://github.com/Sina-Soltani/Parbad/releases/tag/v3.10.0
@@ -47,7 +47,7 @@ More information: https://github.com/Sina-Soltani/Parbad
-
+
diff --git a/src/Parbad/src/Parbad.xml b/src/Parbad/src/Parbad.xml
index 59501fb2..4558b169 100644
--- a/src/Parbad/src/Parbad.xml
+++ b/src/Parbad/src/Parbad.xml
@@ -717,9 +717,34 @@
-
+
- Equals to ReferenceID in Parbad system.
+ API provided by Pasargad Bank.
+
+
+
+
+ Gets a token to start a payment request.
+
+
+
+
+ Verifies a payment.
+
+
+
+
+ Refunds an already paid invoice.
+
+
+
+
+ An Encryptor to sign data which will be sent by each request to Pasargad gateway.
+
+
+
+
+ Encrypts the given data using the provided Private Key.
@@ -740,6 +765,13 @@
+
+
+ Configures the HttpClient for .
+
+ Implementation type of .
+
+
Configures the accounts for .
@@ -754,12 +786,38 @@
Configuration
+
+
+ Registers an Encryptor for .
+
+
+
+
+ Registers an Encryptor for .
+
+
+
+
+ Registers an Encryptor for .
+
+
The invoice will be sent to Pasargad gateway.
+
+
+ Sets additional data that will be sent to Pasargad gateway when requesting a token.
+
+
+
+
+
+ Additional Data that can be sent to Pasargad gateway when requesting a token.
+
+
@@ -918,6 +976,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1907,6 +1980,12 @@
Gets an instance of .
+
+
+
+
+
+
diff --git a/src/Parbad/src/Storage/StorageBuilderExtensions.cs b/src/Parbad/src/Storage/StorageBuilderExtensions.cs
index 7d71b656..63b49743 100644
--- a/src/Parbad/src/Storage/StorageBuilderExtensions.cs
+++ b/src/Parbad/src/Storage/StorageBuilderExtensions.cs
@@ -7,37 +7,37 @@
using Parbad.Storage.Abstractions;
using System;
-namespace Parbad.Builder
+namespace Parbad.Builder;
+
+public static class StorageBuilderExtensions
{
- public static class StorageBuilderExtensions
+ ///
+ /// Configures the storage which required by Parbad for saving and loading data.
+ ///
+ ///
+ ///
+ public static IParbadBuilder ConfigureStorage(this IParbadBuilder builder, Action configureStorage)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (configureStorage == null) throw new ArgumentNullException(nameof(configureStorage));
+
+ var storageBuilder = new StorageBuilder(builder.Services);
+ storageBuilder.UseDefaultStorageManager();
+
+ configureStorage(storageBuilder);
+
+ return builder;
+ }
+
+ ///
+ /// Uses the default implementation of .
+ ///
+ ///
+ [Obsolete("StorageManager will be removed in a future release. The implementations are moved to the IStorage interface.")]
+ public static IStorageBuilder UseDefaultStorageManager(this IStorageBuilder builder)
{
- ///
- /// Configures the storage which required by Parbad for saving and loading data.
- ///
- ///
- ///
- public static IParbadBuilder ConfigureStorage(this IParbadBuilder builder, Action configureStorage)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (configureStorage == null) throw new ArgumentNullException(nameof(configureStorage));
-
- var storageBuilder = new StorageBuilder(builder.Services);
- storageBuilder.UseDefaultStorageManager();
-
- configureStorage(storageBuilder);
-
- return builder;
- }
-
- ///
- /// Uses the default implementation of .
- ///
- ///
- public static IStorageBuilder UseDefaultStorageManager(this IStorageBuilder builder)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
-
- return builder.AddStorageManager(ServiceLifetime.Transient);
- }
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+
+ return builder.AddStorageManager(ServiceLifetime.Transient);
}
}
diff --git a/src/Parbad/src/Storage/StorageManager.cs b/src/Parbad/src/Storage/StorageManager.cs
index 7c3123d3..b526aefa 100644
--- a/src/Parbad/src/Storage/StorageManager.cs
+++ b/src/Parbad/src/Storage/StorageManager.cs
@@ -1,6 +1,7 @@
// Copyright (c) Parbad. All rights reserved.
// Licensed under the GNU GENERAL PUBLIC License, Version 3.0. See License.txt in the project root for license information.
+using System;
using Parbad.Storage.Abstractions;
using Parbad.Storage.Abstractions.Models;
using System.Collections.Generic;
@@ -8,71 +9,71 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Parbad.Storage
+namespace Parbad.Storage;
+
+///
+[Obsolete("This interface will be removed in a future release.")]
+public class StorageManager : IStorageManager
{
- ///
- public class StorageManager : IStorageManager
+ ///
+ /// Initializes an instance of .
+ ///
+ ///
+ [Obsolete("This interface will be removed in a future release. All methods are moved to IStorage interface.")]
+ public StorageManager(IStorage storage)
{
- ///
- /// Initializes an instance of .
- ///
- ///
- public StorageManager(IStorage storage)
- {
- Storage = storage;
- }
-
- ///
- /// Gets an instance of .
- ///
- protected IStorage Storage { get; }
-
- ///
- public virtual Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- => Storage.CreatePaymentAsync(payment, cancellationToken);
-
- ///
- public virtual Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default)
- => Storage.UpdatePaymentAsync(payment, cancellationToken);
-
- ///
- public virtual Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
- => Storage.CreateTransactionAsync(transaction, cancellationToken);
-
- ///
- public virtual Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- return Task.FromResult(Storage.Payments.SingleOrDefault(model => model.TrackingNumber == trackingNumber));
- }
-
- ///
- public virtual Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- return Task.FromResult(Storage.Payments.SingleOrDefault(model => model.Token == paymentToken));
- }
-
- ///
- public virtual Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- return Task.FromResult(Storage.Payments.Any(model => model.TrackingNumber == trackingNumber));
- }
-
- ///
- public virtual Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(Storage.Payments.Any(model => model.Token == paymentToken));
- }
-
- ///
- public virtual Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default)
- {
- return Task.FromResult(Storage.Transactions.Where(model => model.PaymentId == payment.Id).ToList());
- }
+ Storage = storage;
}
+
+ ///
+ /// Gets an instance of .
+ ///
+ protected IStorage Storage { get; }
+
+ ///
+ public IQueryable Payments => Storage.Payments;
+
+ ///
+ public IQueryable Transactions => Storage.Transactions;
+
+ ///
+ public virtual Task CreatePaymentAsync(Payment payment, CancellationToken cancellationToken = default) =>
+ Storage.CreatePaymentAsync(payment, cancellationToken);
+
+ ///
+ public virtual Task UpdatePaymentAsync(Payment payment, CancellationToken cancellationToken = default) =>
+ Storage.UpdatePaymentAsync(payment, cancellationToken);
+
+ public Task DeletePaymentAsync(Payment payment, CancellationToken cancellationToken = default) =>
+ Storage.DeletePaymentAsync(payment, cancellationToken);
+
+ ///
+ public virtual Task CreateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default) =>
+ Storage.CreateTransactionAsync(transaction, cancellationToken);
+
+ public Task UpdateTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default) =>
+ Storage.UpdateTransactionAsync(transaction, cancellationToken);
+
+ public Task DeleteTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default) =>
+ Storage.DeleteTransactionAsync(transaction, cancellationToken);
+
+ ///
+ public virtual Task GetPaymentByTrackingNumberAsync(long trackingNumber, CancellationToken cancellationToken = default) =>
+ Storage.GetPaymentByTrackingNumberAsync(trackingNumber, cancellationToken);
+
+ ///
+ public virtual Task GetPaymentByTokenAsync(string paymentToken, CancellationToken cancellationToken = default) =>
+ Storage.GetPaymentByTokenAsync(paymentToken, cancellationToken);
+
+ ///
+ public virtual Task DoesPaymentExistAsync(long trackingNumber, CancellationToken cancellationToken = default) =>
+ Storage.DoesPaymentExistAsync(trackingNumber, cancellationToken);
+
+ ///
+ public virtual Task DoesPaymentExistAsync(string paymentToken, CancellationToken cancellationToken = default) =>
+ Storage.DoesPaymentExistAsync(paymentToken, cancellationToken);
+
+ ///
+ public virtual Task> GetTransactionsAsync(Payment payment, CancellationToken cancellationToken = default) =>
+ Storage.GetTransactionsAsync(payment, cancellationToken);
}
diff --git a/src/Parbad/tests/Gateway/Pasargad/PasargadGatewayTests.cs b/src/Parbad/tests/Gateway/Pasargad/PasargadGatewayTests.cs
deleted file mode 100644
index b45a6903..00000000
--- a/src/Parbad/tests/Gateway/Pasargad/PasargadGatewayTests.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
-using Microsoft.Extensions.Primitives;
-using Moq;
-using Parbad.Builder;
-using Parbad.Gateway.Pasargad;
-using Parbad.Tests.Helpers;
-using RichardSzalay.MockHttp;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Parbad.Tests.Gateway.Pasargad
-{
- [TestClass]
- public class PasargadGatewayTests
- {
- private IPasargadCrypto _crypto;
-
- private const long ExpectedTrackingNumber = 1;
- private const long ExpectedAmount = 1000;
- private const string ExpectedTransactionCode = "test";
- private const string ExpectedMerchantCode = "test";
- private const string ExpectedTerminalCode = "test";
- private const string ExpectedActionNumber = "1003";
- private const string ExpectedSignedValue = "test";
-
- [TestInitialize]
- public void Setup()
- {
- var mockCrypto = new Mock();
- mockCrypto
- .Setup(crypto => crypto.Encrypt(It.IsAny(), It.IsAny()))
- .Returns(ExpectedSignedValue);
-
- _crypto = mockCrypto.Object;
- }
-
- [TestMethod]
- public async Task Requesting_And_Verifying_Work()
- {
- const string expectedCallbackUrl = "http://www.mywebsite.com";
- const string apiCheckPaymentUrl = "http://localhost/CheckTransactionResult";
- const string apiVerificationUrl = "http://localhost/VerifyPayment";
- const string paymentPageUrl = "http://localhost/";
-
- await GatewayTestHelpers.TestGatewayAsync(
- gateways =>
- {
- var builder = gateways
- .AddPasargad()
- .WithAccounts(accounts =>
- {
- accounts.AddInMemory(account =>
- {
- account.PrivateKey = "test";
- account.MerchantCode = ExpectedMerchantCode;
- account.TerminalCode = ExpectedTerminalCode;
- });
- })
- .WithOptions(options =>
- {
- options.ApiCheckPaymentUrl = apiCheckPaymentUrl;
- options.ApiVerificationUrl = apiVerificationUrl;
- options.PaymentPageUrl = paymentPageUrl;
- });
-
- builder.Services.RemoveAll();
-
- builder.Services.AddSingleton(_crypto);
-
- return builder;
- },
- invoice =>
- {
- invoice
- .SetTrackingNumber(ExpectedTrackingNumber)
- .SetAmount(ExpectedAmount)
- .SetCallbackUrl(expectedCallbackUrl)
- .UsePasargad();
- },
- handler =>
- {
- handler
- .When("*CheckTransactionResult")
- .Respond(MediaTypes.Xml, GetCheckCallbackResponse());
-
- handler
- .When("*VerifyPayment")
- .Respond(MediaTypes.Xml, GetVerificationResponse());
- },
- context =>
- {
- context.Request.Query = new QueryCollection(new Dictionary
- {
- {"iN", ExpectedTrackingNumber.ToString()},
- {"iD", "test"},
- {"tref", ExpectedTransactionCode},
- {"result", "true"}
- });
- },
- result => GatewayOnResultHelper.OnRequestResult(
- result,
- PasargadGateway.Name,
- GatewayTransporterDescriptor.TransportType.Post,
- expectedPaymentPageUrl: paymentPageUrl,
- expectedForm: new Dictionary
- {
- {"merchantCode", ExpectedMerchantCode},
- {"terminalCode", ExpectedTerminalCode},
- {"invoiceNumber", ExpectedTrackingNumber.ToString()},
- {"amount", ExpectedAmount.ToString()},
- {"redirectAddress", expectedCallbackUrl},
- {"action", ExpectedActionNumber},
- {"sign", ExpectedSignedValue}
- }),
- result => GatewayOnResultHelper.OnFetchResult(result, ExpectedTrackingNumber, ExpectedAmount, PasargadGateway.Name),
- result => GatewayOnResultHelper.OnVerifyResult(result, ExpectedTrackingNumber, ExpectedAmount, PasargadGateway.Name, expectedTransactionCode: ExpectedTransactionCode));
- }
-
- private static string GetCheckCallbackResponse()
- {
- return
- "" +
- "" +
- "" +
- $"{ExpectedTrackingNumber}" +
- $"{ExpectedActionNumber}" +
- $"{ExpectedMerchantCode}" +
- $"{ExpectedTerminalCode}" +
- "true" +
- "" +
- "" +
- "";
- }
-
- private static string GetVerificationResponse()
- {
- return
- "" +
- "" +
- "" +
- "true" +
- "" +
- "" +
- "";
- }
- }
-}
diff --git a/src/Parbad/tests/Parbad.Tests.csproj b/src/Parbad/tests/Parbad.Tests.csproj
index 33b14e7d..487bb9b6 100644
--- a/src/Parbad/tests/Parbad.Tests.csproj
+++ b/src/Parbad/tests/Parbad.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
latest
false
diff --git a/tests/Parbad.Tests.Helpers/Parbad.Tests.Helpers.csproj b/tests/Parbad.Tests.Helpers/Parbad.Tests.Helpers.csproj
index 17ca70c3..40079985 100644
--- a/tests/Parbad.Tests.Helpers/Parbad.Tests.Helpers.csproj
+++ b/tests/Parbad.Tests.Helpers/Parbad.Tests.Helpers.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1;net5.0;net6.0;net7.0;net8.0
+ netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0
latest
false
@@ -26,7 +26,7 @@
-
+