Session variables should be set and redirects performed only by the controller. I assume you already have some controllers in your components. Add the task to an existing one or create a new one, whichever is more appropriate for your component.
The form:
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
?>
<form method="post" action="<?php echo Route::_('index.php', false); ?>">
<?php // Indicates the component to use ?>
<input type="hidden" name="option" value="com_example">
<?php // The controller and the method to execute ?>
<input type="hidden" name="task" value="download.unlock">
<?php // Set the redirect URL ?>
<input type="hidden" name="return" value="<?php echo base64_encode(Uri::getInstance()); ?>">
<?php // Pass the download ID, assuming there are multiple downloads and each needs to be unlocked separately ?>
<input type="hidden" name="id" value="<?php echo $id; ?>">
<?php // Renders CSRF token ?>
<?php echo HTMLHelper::_('form.token'); ?>
<button type="submit">Unlock</button>
</form>
The controller task:
public function unlock()
{
// Check CSRF token.
$this->checkToken();
// Get the application.
$app = Factory::getApplication();
// Check that redirect URL is valid. Otherwise set it to index.php.
$return = $this->input->post->get('return', '', 'BASE64');
if (is_string($return))
{
$return = base64_decode($return);
if (!Uri::isInternal($return))
{
$return = Route::_('index.php', false);
}
}
else
{
$return = Route::_('index.php', false);
}
// Get the download ID.
$id = $this->input->post->get('id', null, 'INT');
// Check that download ID is a valid integer.
if (!is_integer($id))
{
// Invalid ID provided, redirect back.
$this->setRedirect($return, $app->getLanguage()->_('COM_EXAMPLE_DOWNLOAD_UNLOCK_INVALID_ID'));
return;
}
// Set the session variable. Session key be anything, but make sure it's unique.
$app->setUserState('com_example.download.unlock.' . $id, true);
// Redirect back to download page.
$this->setRedirect($return);
}