feat: add payment callback and referral link features
Build and Deploy / build (push) Failing after 1m21s
Build and Deploy / build (push) Failing after 1m21s
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
@page "/profile/payment-callback"
|
||||
@attribute [Authorize]
|
||||
@using Blazored.LocalStorage
|
||||
@using FrontOffice.BFF.Package.Protobuf.Protos.Package
|
||||
@using FrontOffice.BFF.User.Protobuf.Protos.User
|
||||
|
||||
<PageTitle>نتیجه پرداخت | کارا بازار سلامت</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Small" Class="py-8">
|
||||
<MudPaper Class="pa-6 text-center">
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudProgressCircular Color="Color.Primary" Indeterminate="true" Size="Size.Large" />
|
||||
<MudText Typo="Typo.h6" Class="mt-4">در حال بررسی وضعیت پرداخت...</MudText>
|
||||
}
|
||||
else if (_isSuccess)
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Large" Style="font-size: 80px" />
|
||||
<MudText Typo="Typo.h5" Color="Color.Success" Class="mt-4">پرداخت موفق</MudText>
|
||||
<MudText Typo="Typo.body1" Class="mt-2">@_message</MudText>
|
||||
|
||||
@if (!string.IsNullOrEmpty(_refId))
|
||||
{
|
||||
<MudText Typo="Typo.body2" Class="mt-3">
|
||||
<strong>کد پیگیری:</strong> @_refId
|
||||
</MudText>
|
||||
}
|
||||
|
||||
<MudDivider Class="my-4" />
|
||||
|
||||
<MudText Typo="Typo.body2" Color="Color.Secondary">
|
||||
موجودی کیف پول: @FormatPrice(_walletBalance)
|
||||
</MudText>
|
||||
<MudText Typo="Typo.body2" Color="Color.Secondary">
|
||||
موجودی اعتبار تخفیف: @FormatPrice(_discountBalance)
|
||||
</MudText>
|
||||
|
||||
<MudButton Color="Color.Primary" Variant="Variant.Filled" Class="mt-6"
|
||||
Href="/profile">
|
||||
بازگشت به پروفایل
|
||||
</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.Error" Color="Color.Error" Size="Size.Large" Style="font-size: 80px" />
|
||||
<MudText Typo="Typo.h5" Color="Color.Error" Class="mt-4">پرداخت ناموفق</MudText>
|
||||
<MudText Typo="Typo.body1" Class="mt-2">@_message</MudText>
|
||||
|
||||
<MudButton Color="Color.Primary" Variant="Variant.Filled" Class="mt-6"
|
||||
Href="/profile">
|
||||
بازگشت به پروفایل
|
||||
</MudButton>
|
||||
|
||||
<MudButton Color="Color.Secondary" Variant="Variant.Outlined" Class="mt-3 mr-2"
|
||||
OnClick="RetryPayment">
|
||||
تلاش مجدد
|
||||
</MudButton>
|
||||
}
|
||||
</MudPaper>
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
[Inject] private PackageContract.PackageContractClient PackageContractClient { get; set; } = default!;
|
||||
[Inject] private UserContract.UserContractClient UserContractClient { get; set; } = default!;
|
||||
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
||||
[Inject] private AuthService AuthService { get; set; } = default!;
|
||||
[Inject] private NavigationManager NavManager { get; set; } = default!;
|
||||
|
||||
private const string TokenStorageKey = "auth:token";
|
||||
|
||||
[SupplyParameterFromQuery(Name = "orderId")]
|
||||
private long OrderId { get; set; }
|
||||
|
||||
[SupplyParameterFromQuery(Name = "transactionId")]
|
||||
private long TransactionId { get; set; }
|
||||
|
||||
[SupplyParameterFromQuery(Name = "Authority")]
|
||||
private string? Authority { get; set; }
|
||||
|
||||
[SupplyParameterFromQuery(Name = "Status")]
|
||||
private string? Status { get; set; }
|
||||
|
||||
private bool _isLoading = true;
|
||||
private bool _isSuccess;
|
||||
private string _message = string.Empty;
|
||||
private string? _refId;
|
||||
private long _walletBalance;
|
||||
private long _discountBalance;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await VerifyPayment();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task VerifyPayment()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (OrderId <= 0 || TransactionId <= 0 || string.IsNullOrEmpty(Authority))
|
||||
{
|
||||
_isSuccess = false;
|
||||
_message = "پارامترهای پرداخت نامعتبر است";
|
||||
_isLoading = false;
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
var response = await PackageContractClient.VerifyBasePackagePaymentAsync(new VerifyBasePackagePaymentRequest
|
||||
{
|
||||
OrderId = OrderId,
|
||||
TransactionId = TransactionId,
|
||||
Authority = Authority,
|
||||
Status = Status ?? "NOK"
|
||||
});
|
||||
|
||||
_isSuccess = response.Success;
|
||||
_message = response.Message;
|
||||
_refId = response.RefId;
|
||||
_walletBalance = response.WalletBalance;
|
||||
_discountBalance = response.DiscountBalance;
|
||||
|
||||
// اگر پرداخت موفق بود، توکن را refresh میکنیم
|
||||
// چون PackagePurchaseMethod تغییر کرده و باید در claims جدید باشد
|
||||
if (_isSuccess)
|
||||
{
|
||||
await RefreshTokenAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_isSuccess = false;
|
||||
_message = $"خطا در بررسی وضعیت پرداخت: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoading = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void RetryPayment()
|
||||
{
|
||||
NavManager.NavigateTo("/profile");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh token after successful payment to update PackagePurchaseMethod claim
|
||||
/// </summary>
|
||||
private async Task RefreshTokenAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var userResponse = await UserContractClient.GetUserAsync(new Google.Protobuf.WellKnownTypes.Empty());
|
||||
if (!string.IsNullOrWhiteSpace(userResponse.Token))
|
||||
{
|
||||
// ذخیره توکن جدید در localStorage
|
||||
await LocalStorage.SetItemAsync(TokenStorageKey, userResponse.Token);
|
||||
|
||||
// بهروزرسانی UserAuthInfo با claims جدید
|
||||
await AuthService.InitUserAuthInfo();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// اگر refresh ناموفق بود، پرداخت همچنان موفق است
|
||||
// کاربر میتواند با logout/login دوباره token جدید بگیرد
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);
|
||||
}
|
||||
Reference in New Issue
Block a user