320 lines
9.9 KiB
C#
320 lines
9.9 KiB
C#
using DateTimeConverterCL;
|
|
using CMSMicroservice.Protobuf.Protos.UserWallet;
|
|
using Google.Protobuf.WellKnownTypes;
|
|
|
|
namespace FrontOffice.Main.Utilities;
|
|
|
|
public record WalletBalances(long CreditBalance, long DiscountBalance, long NetworkBalance);
|
|
public record WalletTransaction(
|
|
string Date,
|
|
long CreditChange,
|
|
long CreditBalance,
|
|
long NetworkChange,
|
|
long NetworkBalance,
|
|
long DiscountChange,
|
|
long DiscountBalance,
|
|
string Channel,
|
|
string Description
|
|
);
|
|
public record WalletWithdrawal(long Id, long WeekDefinitionId, string WeekDisplayName, long Amount, int Status, int? Method, string? Iban, string Created);
|
|
public enum WithdrawalMethodClient
|
|
{
|
|
Cash = 0,
|
|
Diamond = 1
|
|
}
|
|
public record WithdrawalSettings(long MinWithdrawalAmount);
|
|
|
|
public record MagicWalletStatus(
|
|
int WalletMode,
|
|
long MagicTotalDeposited,
|
|
long MagicTotalCredited,
|
|
long MagicMaxDeposit,
|
|
long MagicRemainingDeposit,
|
|
long Balance,
|
|
DateTime? MagicActivatedAt,
|
|
int PurchaseCycleCount,
|
|
double MagicMultiplier = 2.5,
|
|
long MagicMaxCredit = 2_500_000_000
|
|
);
|
|
|
|
public class WalletService
|
|
{
|
|
private readonly CMSMicroservice.Protobuf.Protos.UserWallet.UserWalletContract.UserWalletContractClient _client;
|
|
|
|
public WalletService(CMSMicroservice.Protobuf.Protos.UserWallet.UserWalletContract.UserWalletContractClient client)
|
|
{
|
|
_client = client;
|
|
}
|
|
|
|
public async Task<WalletBalances> GetBalancesAsync()
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.GetCustomerWalletAsync(new Empty());
|
|
return new WalletBalances(response.Balance, response.DiscountBalance, response.NetworkBalance);
|
|
}
|
|
catch
|
|
{
|
|
// Return zero balances if backend is unavailable
|
|
return new WalletBalances(0, 0, 0);
|
|
}
|
|
}
|
|
|
|
public async Task<List<WalletTransaction>> GetTransactionsAsync(long? referenceId = null, bool? isIncrease = null)
|
|
{
|
|
try
|
|
{
|
|
var request = new GetCustomerWalletHistoryRequest();
|
|
if (referenceId.HasValue)
|
|
{
|
|
request.ReferenceId = referenceId.Value;
|
|
}
|
|
if (isIncrease.HasValue)
|
|
{
|
|
request.IsIncrease = isIncrease.Value;
|
|
}
|
|
var response = await _client.GetCustomerWalletHistoryAsync(request);
|
|
|
|
return response.Models
|
|
.Select(log => new WalletTransaction(
|
|
ResolveTransactionDate(log),
|
|
log.ChangeValue,
|
|
log.CurrentBalance,
|
|
log.ChangeNerworkValue,
|
|
log.CurrentNetworkBalance,
|
|
log.ChangeDiscountValue,
|
|
log.CurrentDiscountBalance,
|
|
log.RefrenceId?.ToString() ?? "-",
|
|
ResolveDescription(log)
|
|
))
|
|
.OrderByDescending(t => t.Date)
|
|
.ToList();
|
|
}
|
|
catch
|
|
{
|
|
// Return empty list if backend is unavailable
|
|
return new List<WalletTransaction>();
|
|
}
|
|
}
|
|
|
|
private static string ResolveTransactionDate(CustomerWalletHistoryModel model)
|
|
{
|
|
if (model.CreatedAt is not null)
|
|
{
|
|
try
|
|
{
|
|
var utcDate = model.CreatedAt.ToDateTime();
|
|
return utcDate.ToLocalTime().MiladiToJalaliWithTime();
|
|
}
|
|
catch
|
|
{
|
|
// ignore conversion issues and fall through to default
|
|
}
|
|
}
|
|
|
|
return DateTime.Now.MiladiToJalaliWithTime();
|
|
}
|
|
|
|
private static string ResolveDescription(CustomerWalletHistoryModel model)
|
|
{
|
|
var parts = new List<string>();
|
|
|
|
if (model.ChangeValue != 0)
|
|
parts.Add(model.ChangeValue > 0 ? "شارژ اصلی" : "برداشت اصلی");
|
|
|
|
if (model.ChangeNerworkValue != 0)
|
|
parts.Add(model.ChangeNerworkValue > 0 ? "دریافت پاداش تیمی" : "برداشت پاداش تیمی");
|
|
|
|
if (model.ChangeDiscountValue != 0)
|
|
parts.Add(model.ChangeDiscountValue > 0 ? "شارژ اعتباری" : "خرید اعتباری");
|
|
|
|
return parts.Count > 0 ? string.Join(" | ", parts) : "تراکنش کیف پول";
|
|
}
|
|
|
|
public async Task<bool> RequestWithdrawalAsync(long payoutId, WithdrawalMethodClient method, string? iban)
|
|
{
|
|
var request = new CustomerWithdrawBalanceRequest
|
|
{
|
|
PayoutId = payoutId,
|
|
WithdrawalMethod = (int)method
|
|
};
|
|
if (!string.IsNullOrWhiteSpace(iban))
|
|
{
|
|
request.IbanNumber = iban;
|
|
}
|
|
try
|
|
{
|
|
await _client.CustomerWithdrawBalanceAsync(request);
|
|
return true;
|
|
}
|
|
catch (Grpc.Core.RpcException ex)
|
|
{
|
|
throw new InvalidOperationException(ex.Status.Detail ?? "خطا در ثبت برداشت", ex);
|
|
}
|
|
}
|
|
|
|
public async Task<List<WalletWithdrawal>> GetWithdrawalsAsync(int? status = null)
|
|
{
|
|
try
|
|
{
|
|
var request = new GetCustomerWithdrawalsRequest();
|
|
if (status.HasValue)
|
|
{
|
|
request.Status = status.Value;
|
|
}
|
|
|
|
var response = await _client.GetCustomerWithdrawalsAsync(request);
|
|
return response.Models
|
|
.Select(m => new WalletWithdrawal(
|
|
m.Id,
|
|
m.WeekDefinitionId,
|
|
m.WeekDisplayName,
|
|
m.TotalAmount,
|
|
m.Status,
|
|
m.WithdrawalMethod,
|
|
m.IbanNumber,
|
|
m.Created?.ToDateTime().MiladiToJalaliWithTime() ?? "-"))
|
|
.ToList();
|
|
}
|
|
catch
|
|
{
|
|
return new List<WalletWithdrawal>();
|
|
}
|
|
}
|
|
|
|
public async Task<WithdrawalSettings> GetWithdrawalSettingsAsync()
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.GetCustomerWithdrawalSettingsAsync(new Empty());
|
|
return new WithdrawalSettings(response.MinWithdrawalAmount);
|
|
}
|
|
catch
|
|
{
|
|
// Return default settings if backend is unavailable
|
|
return new WithdrawalSettings(0);
|
|
}
|
|
}
|
|
|
|
// ============= Magic Wallet =============
|
|
|
|
public async Task<MagicWalletStatus> GetMagicWalletStatusAsync()
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.GetMagicWalletStatusAsync(new Empty());
|
|
DateTime? activatedAt = response.MagicActivatedAt != null
|
|
? response.MagicActivatedAt.ToDateTime().ToLocalTime()
|
|
: null;
|
|
|
|
return new MagicWalletStatus(
|
|
response.WalletMode,
|
|
response.MagicTotalDeposited,
|
|
response.MagicTotalCredited,
|
|
response.MagicMaxDeposit,
|
|
response.MagicRemainingDeposit,
|
|
response.Balance,
|
|
activatedAt,
|
|
response.PurchaseCycleCount,
|
|
response.MagicMultiplier > 0 ? response.MagicMultiplier : 2.5,
|
|
response.MagicMaxCredit > 0 ? response.MagicMaxCredit : 2_500_000_000
|
|
);
|
|
}
|
|
catch
|
|
{
|
|
return new MagicWalletStatus(0, 0, 0, 0, 0, 0, null, 0);
|
|
}
|
|
}
|
|
|
|
public async Task<(bool Success, string? GatewayUrl, string? Error)> InitiateMagicChargeAsync(long amount)
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.InitiateMagicChargeAsync(new InitiateMagicChargeRequest
|
|
{
|
|
Amount = amount
|
|
});
|
|
|
|
if (response.IsSuccess)
|
|
return (true, response.GatewayUrl, null);
|
|
|
|
return (false, null, response.ErrorMessage);
|
|
}
|
|
catch (Grpc.Core.RpcException ex)
|
|
{
|
|
return (false, null, ex.Status.Detail ?? "خطا در ارتباط با سرور");
|
|
}
|
|
}
|
|
|
|
public async Task<(bool Success, string? GatewayUrl, string? Error)> InitiateDiscountChargeAsync(long amount)
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.InitiateDiscountChargeAsync(new InitiateDiscountChargeRequest
|
|
{
|
|
Amount = amount
|
|
});
|
|
|
|
if (response.IsSuccess)
|
|
return (true, response.GatewayUrl, null);
|
|
|
|
return (false, null, response.ErrorMessage);
|
|
}
|
|
catch (Grpc.Core.RpcException ex)
|
|
{
|
|
return (false, null, ex.Status.Detail ?? "خطا در ارتباط با سرور");
|
|
}
|
|
}
|
|
|
|
// ============= Wallet Verify Methods =============
|
|
|
|
public async Task<(bool Success, string Message)> VerifyMagicChargeAsync(string authority, string status)
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.VerifyMagicChargeAsync(new VerifyWalletChargeRequest
|
|
{
|
|
Authority = authority,
|
|
Status = status
|
|
});
|
|
|
|
return (response.Success, response.Message);
|
|
}
|
|
catch (Grpc.Core.RpcException ex)
|
|
{
|
|
return (false, ex.Status.Detail ?? "خطا در بررسی وضعیت پرداخت");
|
|
}
|
|
}
|
|
|
|
public async Task<(bool Success, string Message)> VerifyDiscountChargeAsync(string authority, string status)
|
|
{
|
|
try
|
|
{
|
|
var response = await _client.VerifyDiscountChargeAsync(new VerifyWalletChargeRequest
|
|
{
|
|
Authority = authority,
|
|
Status = status
|
|
});
|
|
|
|
return (response.Success, response.Message);
|
|
}
|
|
catch (Grpc.Core.RpcException ex)
|
|
{
|
|
return (false, ex.Status.Detail ?? "خطا در بررسی وضعیت پرداخت");
|
|
}
|
|
}
|
|
|
|
public int GetWalletMode()
|
|
{
|
|
try
|
|
{
|
|
var response = _client.GetCustomerWallet(new Empty());
|
|
return response.WalletMode;
|
|
}
|
|
catch
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|