feat(wallet): add credit wallet functionality and update Protobuf definitions
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m49s

- Introduced new CreditWalletCharge enum value to TransactionType for clarity.
- Implemented InitiateCreditCharge and VerifyCreditCharge methods in UserWalletService for handling credit wallet transactions.
- Updated ZarinpalReconciliationJob to support credit wallet payment verification.
- Enhanced Protobuf definitions with new messages and RPC methods for credit wallet operations.
- Bumped Protobuf project version to reflect the addition of new features.
This commit is contained in:
masoodafar-web
2026-06-26 16:11:18 +03:30
parent 7570c39e65
commit 6c3fbe43b1
10 changed files with 462 additions and 1 deletions
@@ -5,8 +5,10 @@ using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
using CMSMicroservice.Application.WalletCQ.Commands.ChargeMagicWallet;
using CMSMicroservice.Application.WalletCQ.Commands.ChargeDiscountWallet;
using CMSMicroservice.Application.WalletCQ.Commands.ChargeCreditWallet;
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
using CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
@@ -242,6 +244,38 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
}
}
// ============= Credit (Main) Wallet Methods =============
public override async Task<InitiateCreditChargeResponse> InitiateCreditCharge(
InitiateCreditChargeRequest request, ServerCallContext context)
{
var userId = GetCurrentUserId();
try
{
var result = await _sender.Send(new ChargeCreditWalletCommand
{
UserId = userId,
Amount = request.Amount
}, context.CancellationToken);
return new InitiateCreditChargeResponse
{
IsSuccess = result.IsSuccess,
GatewayUrl = result.GatewayUrl ?? "",
ErrorMessage = result.ErrorMessage ?? ""
};
}
catch (PaymentInProgressException ex)
{
return new InitiateCreditChargeResponse
{
IsSuccess = false,
ErrorMessage = ex.Message
};
}
}
// ============= Wallet Verify Methods =============
public override async Task<VerifyWalletChargeResponse> VerifyMagicCharge(
@@ -330,6 +364,57 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
}
}
public override async Task<VerifyWalletChargeResponse> VerifyCreditCharge(
VerifyWalletChargeRequest request, ServerCallContext context)
{
_logger.LogInformation("VerifyCreditCharge called: Authority={Authority}, Status={Status}",
request.Authority, request.Status);
try
{
if (string.IsNullOrEmpty(request.Authority))
return new VerifyWalletChargeResponse { Success = false, Message = "کد Authority نامعتبر است" };
var paymentTx = await _context.PaymentTransactions
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
if (paymentTx == null || !paymentTx.UserId.HasValue)
{
_logger.LogError("VerifyCreditCharge: PaymentTransaction not found for Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = "تراکنش یافت نشد" };
}
if (!string.Equals(request.Status, "OK", StringComparison.OrdinalIgnoreCase))
{
_logger.LogWarning("VerifyCreditCharge: Payment cancelled by user. Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = "پرداخت توسط کاربر لغو شد" };
}
var result = await _sender.Send(new VerifyCreditWalletChargeCommand
{
UserId = paymentTx.UserId.Value,
Amount = paymentTx.Amount,
Authority = request.Authority
}, context.CancellationToken);
_logger.LogInformation("VerifyCreditCharge result: {Result}, Authority={Authority}, UserId={UserId}",
result, request.Authority, paymentTx.UserId.Value);
return new VerifyWalletChargeResponse
{
Success = result,
Message = result
? "شارژ کیف پول اصلی با موفقیت انجام شد"
: "شارژ کیف پول اصلی ناموفق بود"
};
}
catch (Exception ex)
{
_logger.LogError(ex, "VerifyCreditCharge error: Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = ex.Message };
}
}
public override async Task<GetMagicWalletStatusResponse> GetMagicWalletStatus(
Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
{