feat: Update payment processing and callback mechanisms
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m22s

- Refactor ActivateClubMembershipCommandHandler to use UserPackagePurchases instead of UserOrders for package activation.
- Modify PlaceOrderCommandHandler to redirect payment callbacks to the front office.
- Update ChargeDiscountWalletCommandHandler and ChargeMagicWalletCommandHandler to direct payment callbacks to the front office.
- Remove PaymentCallbackController and integrate payment verification directly into DiscountOrderService and UserWalletService.
- Add CustomerVerifyDiscountOrderPayment RPC to DiscountOrderService for verifying discount order payments.
- Implement VerifyMagicCharge and VerifyDiscountCharge methods in UserWalletService for wallet charge verifications.
- Update appsettings.json to use local URLs for development.
- Remove appsettings.Development.json as it is no longer needed.
- Comment out history tracking methods in ClubMembershipCycle and Package classes.
- Update PackageService to automatically activate club membership after successful payment verification.
- Adjust UserService to generate JWT tokens with user details.
This commit is contained in:
masoodafar-web
2026-02-28 03:27:46 +03:30
parent 01073084ab
commit 1e7c17f090
17 changed files with 363 additions and 334 deletions
@@ -5,6 +5,8 @@ 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.VerifyMagicWalletCharge;
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
@@ -16,6 +18,7 @@ using CMSMicroservice.Domain.Enums;
using Grpc.Core;
using Google.Protobuf.WellKnownTypes;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Linq;
namespace CMSMicroservice.WebApi.Services;
@@ -25,17 +28,20 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
private readonly ISender _sender;
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUserService;
private readonly ILogger<UserWalletService> _logger;
public UserWalletService(
IDispatchRequestToCQRS dispatchRequestToCQRS,
ISender sender,
IApplicationDbContext context,
ICurrentUserService currentUserService)
ICurrentUserService currentUserService,
ILogger<UserWalletService> logger)
{
_dispatchRequestToCQRS = dispatchRequestToCQRS;
_sender = sender;
_context = context;
_currentUserService = currentUserService;
_logger = logger;
}
public override async Task<CreateNewUserWalletResponse> CreateNewUserWallet(CreateNewUserWalletRequest request, ServerCallContext context)
{
@@ -213,6 +219,94 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
};
}
// ============= Wallet Verify Methods =============
public override async Task<VerifyWalletChargeResponse> VerifyMagicCharge(
VerifyWalletChargeRequest request, ServerCallContext context)
{
_logger.LogInformation("VerifyMagicCharge called: Authority={Authority}, Status={Status}",
request.Authority, request.Status);
try
{
if (string.IsNullOrEmpty(request.Authority))
return new VerifyWalletChargeResponse { Success = false, Message = "کد Authority نامعتبر است" };
var result = await _sender.Send(new VerifyMagicWalletChargeCommand
{
Authority = request.Authority,
Status = request.Status ?? "NOK"
}, context.CancellationToken);
_logger.LogInformation("VerifyMagicCharge result: {Result}, Authority={Authority}", result, request.Authority);
return new VerifyWalletChargeResponse
{
Success = result,
Message = result
? "شارژ کیف‌پول جادویی با موفقیت انجام شد"
: "شارژ کیف‌پول جادویی ناموفق بود"
};
}
catch (Exception ex)
{
_logger.LogError(ex, "VerifyMagicCharge error: Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = ex.Message };
}
}
public override async Task<VerifyWalletChargeResponse> VerifyDiscountCharge(
VerifyWalletChargeRequest request, ServerCallContext context)
{
_logger.LogInformation("VerifyDiscountCharge called: Authority={Authority}, Status={Status}",
request.Authority, request.Status);
try
{
if (string.IsNullOrEmpty(request.Authority))
return new VerifyWalletChargeResponse { Success = false, Message = "کد Authority نامعتبر است" };
// پیدا کردن PaymentTransaction برای استخراج UserId و Amount
var paymentTx = await _context.PaymentTransactions
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
if (paymentTx == null || !paymentTx.UserId.HasValue)
{
_logger.LogError("VerifyDiscountCharge: PaymentTransaction not found for Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = "تراکنش یافت نشد" };
}
if (!string.Equals(request.Status, "OK", StringComparison.OrdinalIgnoreCase))
{
_logger.LogWarning("VerifyDiscountCharge: Payment cancelled by user. Authority={Authority}", request.Authority);
return new VerifyWalletChargeResponse { Success = false, Message = "پرداخت توسط کاربر لغو شد" };
}
var result = await _sender.Send(new VerifyDiscountWalletChargeCommand
{
UserId = paymentTx.UserId.Value,
Amount = paymentTx.Amount,
Authority = request.Authority
}, context.CancellationToken);
_logger.LogInformation("VerifyDiscountCharge 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, "VerifyDiscountCharge 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)
{