Interestingly I did all my testing with a Windows 10 and Windows 11 laptop until I was happy with my captive portal. I tested at each stage:
set up captive portal with defaults, no authentication.
set up voucher roll and voucher authentication.
add SSL certificate (I already use an ACME letsencrypt with pfsense so I added another URL to the SAN for the captive portal)
set up radius
customise the logon HTML and the "error" HTML
I was happy that this all worked - only the "edge browser" seems to have an oddity with captive portal (force redirect sorted that and I was going to force redirect to my "company landing page" anyway, chrome and firefox have no issue sending its captive portal check plus redirecting back. Now to test with other devices:
*Ipad worked fine.
*Android did not. Android was convinced that it was connected - it attempted a www.gstatic.com/generate_204 which apparently (according to the device) succeeded pre authentication! There was no traffic flow though (good). However I could not get the captive portal page to trigger on an android device, it was convinced that it needed to "sign in" but then would simply say that it was connected.
I spent quite a lot of time looking at firewall logs, device logs and trying to fathom why the android device was convinced it had a connectivity allowed and I was never shown the captive portal page, I checked everything from DNS (I use pfsense forwarder and there is only one "exception" which is a "disclaimer landing page" simple URL on a local webserver).
In the end I found that if I "disconnected all users" then this would work. After digging it seems that if I make a change to the pfsense portal settings I need to disconnect all users for my android device to see the captive portal. Most odd.
Android device is version 12. I have no idea what this will do to the people who have vouchers when I disconnect (radius auth will be irrelevant of course, they can re-sign in.