I have resolved the issue by first adding @rendermode InteractiveServer to the page since I'm using a Blazor server application and by removing the OnInitializedAsync() method from the code so the final code becomes:
@page "/checkout"
@attribute [Authorize]
@rendermode InteractiveServer
@inject AuthenticationStateProvider _authStateProvider
@inject ICartService _cartService
@inject IUserService _userService
@inject IConfiguration _configuration
@inject IJSRuntime JS
@inject NavigationManager _navigation
<PageTitle>Checkout | LearnSpace</PageTitle>
<SectionContent SectionName="page-header-title">Checkout</SectionContent>
<div>
<h2>Checkout</h2>
<button class="btn btn-primary" @onclick="ProcessCheckout">Place Order</button>
<a href="/cart" class="btn btn-secondary">Back to Shopping Bag</a>
</div>
@code {
private bool shouldRedirect;
private string authorizationUrl;
private bool shouldOpenInNewTab = false;
private async Task ProcessCheckout()
{
try
{
// Initialize checkout process
var userId = await GetUserIdAsync();
var netTotal = await _cartService.GetBasketNetTotalAsync(userId);
var authState = await _authStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
string strEmail = user.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;
string token = _configuration["PayStackSettings:PayStackSecretKey"];
var payStack = new PayStackApi(token);
TransactionInitializeRequest request = new()
{
AmountInKobo = Convert.ToInt32(netTotal) * 100,
Email = strEmail,
Reference = Generate().ToString(),
Currency = "GHS"
};
// Initiate transaction
var response = payStack.Transactions.Initialize(request);
if (response.Status)
{
authorizationUrl = response.Data.AuthorizationUrl;
shouldOpenInNewTab = true;
StateHasChanged(); // Trigger re-render to ensure OnAfterRenderAsync runs
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (shouldOpenInNewTab && authorizationUrl != null)
{
shouldOpenInNewTab = false; // Reset the flag after the redirect
await JS.InvokeVoidAsync("openInNewTab", authorizationUrl);
}
}
private async Task<string> GetUserIdAsync()
{
var authState = await _authStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
return user.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
}
private static int Generate() => new Random((int)DateTime.Now.Ticks).Next(100000000, 999999999);
}
So that's it.