feat: ChargeDiscountWallet - callback endpoint, gRPC RPC & service implementation
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 10m43s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 10m43s
- Add /api/wallet/verify-discount-charge callback endpoint in PaymentCallbackController - Add InitiateDiscountCharge RPC + request/response messages in userwallet.proto - Add InitiateDiscountCharge gRPC service override in UserWalletService - Add ChargeDiscountWallet using import for handler resolution
This commit is contained in:
@@ -88,6 +88,15 @@ service UserWalletContract
|
|||||||
get: "/Customer/GetMagicWalletStatus"
|
get: "/Customer/GetMagicWalletStatus"
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============= Discount Wallet Methods =============
|
||||||
|
|
||||||
|
rpc InitiateDiscountCharge(InitiateDiscountChargeRequest) returns (InitiateDiscountChargeResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/Customer/InitiateDiscountCharge"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
message CreateNewUserWalletRequest
|
message CreateNewUserWalletRequest
|
||||||
{
|
{
|
||||||
@@ -242,3 +251,17 @@ message GetMagicWalletStatusResponse
|
|||||||
google.protobuf.Timestamp magic_activated_at = 7;
|
google.protobuf.Timestamp magic_activated_at = 7;
|
||||||
int32 purchase_cycle_count = 8; // تعداد دورهای خرید پکیج (0 = هنوز هیچ دوری تکمیل نشده)
|
int32 purchase_cycle_count = 8; // تعداد دورهای خرید پکیج (0 = هنوز هیچ دوری تکمیل نشده)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============= Discount Wallet Messages =============
|
||||||
|
|
||||||
|
message InitiateDiscountChargeRequest
|
||||||
|
{
|
||||||
|
int64 amount = 1; // مبلغ واریزی (ریال)
|
||||||
|
}
|
||||||
|
|
||||||
|
message InitiateDiscountChargeResponse
|
||||||
|
{
|
||||||
|
bool is_success = 1;
|
||||||
|
string gateway_url = 2;
|
||||||
|
string error_message = 3;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
||||||
|
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
||||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@@ -186,4 +187,63 @@ public class PaymentCallbackController : ControllerBase
|
|||||||
return Redirect($"{frontOfficeBaseUrl}/magic-wallet?payment=failed");
|
return Redirect($"{frontOfficeBaseUrl}/magic-wallet?payment=failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback برای شارژ کیفپول تخفیفی — زرینپال بعد از پرداخت کاربر را اینجا برمیگرداند
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("/api/wallet/verify-discount-charge")]
|
||||||
|
public async Task<IActionResult> DiscountChargeCallback(
|
||||||
|
[FromQuery(Name = "Authority")] string? authority,
|
||||||
|
[FromQuery(Name = "Status")] string? status,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268";
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Discount charge callback received: Authority={Authority}, Status={Status}",
|
||||||
|
authority, status);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(authority))
|
||||||
|
{
|
||||||
|
_logger.LogError("Discount charge callback: Authority is missing");
|
||||||
|
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=error&reason=no-authority");
|
||||||
|
}
|
||||||
|
|
||||||
|
// پیدا کردن PaymentTransaction برای استخراج UserId و Amount
|
||||||
|
var paymentTx = await _context.PaymentTransactions
|
||||||
|
.FirstOrDefaultAsync(pt => pt.Authority == authority, cancellationToken);
|
||||||
|
|
||||||
|
if (paymentTx == null || !paymentTx.UserId.HasValue)
|
||||||
|
{
|
||||||
|
_logger.LogError("Discount charge callback: PaymentTransaction not found for Authority={Authority}", authority);
|
||||||
|
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=error&reason=tx-not-found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(status, "OK", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Discount charge cancelled by user. Authority={Authority}", authority);
|
||||||
|
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _sender.Send(new VerifyDiscountWalletChargeCommand
|
||||||
|
{
|
||||||
|
UserId = paymentTx.UserId.Value,
|
||||||
|
Amount = paymentTx.Amount,
|
||||||
|
Authority = authority
|
||||||
|
}, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Discount charge completed successfully. Authority={Authority}, UserId={UserId}",
|
||||||
|
authority, paymentTx.UserId.Value);
|
||||||
|
|
||||||
|
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=success");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Discount charge callback error. Authority={Authority}", authority);
|
||||||
|
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using CMSMicroservice.Application.UserWalletCQ.Commands.CreateNewUserWallet;
|
|||||||
using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
|
using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
|
||||||
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
|
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
|
||||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeMagicWallet;
|
using CMSMicroservice.Application.WalletCQ.Commands.ChargeMagicWallet;
|
||||||
|
using CMSMicroservice.Application.WalletCQ.Commands.ChargeDiscountWallet;
|
||||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
|
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
|
||||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
|
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
|
||||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
|
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
|
||||||
@@ -170,6 +171,27 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============= Discount Wallet Methods =============
|
||||||
|
|
||||||
|
public override async Task<InitiateDiscountChargeResponse> InitiateDiscountCharge(
|
||||||
|
InitiateDiscountChargeRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
var userId = GetCurrentUserId();
|
||||||
|
|
||||||
|
var result = await _sender.Send(new ChargeDiscountWalletCommand
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Amount = request.Amount
|
||||||
|
}, context.CancellationToken);
|
||||||
|
|
||||||
|
return new InitiateDiscountChargeResponse
|
||||||
|
{
|
||||||
|
IsSuccess = result.IsSuccess,
|
||||||
|
GatewayUrl = result.GatewayUrl ?? "",
|
||||||
|
ErrorMessage = result.ErrorMessage ?? ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<GetMagicWalletStatusResponse> GetMagicWalletStatus(
|
public override async Task<GetMagicWalletStatusResponse> GetMagicWalletStatus(
|
||||||
Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
|
Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user