To verify fully end-to-end, whilst keeping the same principles of secret-and-private ballots1 the only thing I can think of is to get a hashed value of voterId and the voteCast (singular or array) giving something reasonably non-repeatable so that the voter can take away a small printout that they can later positively verify as also existing within the accumulated list of data at the 'counting' end. But not returning their actual vote.
Trouble is that there are still opportunities to intervene in the process (mislabel touchscreen buttons and onscreen/printout "confirmation" lists2), so there's additional validation necessary.
1 Any mechanism that allows you to go in there and from the final batch of votes and say "see, that's my vote, I voted for you guys like I said..." is going to allow pay-per-vote practices the like of which the "no photography within the polling booth" rule is intended to prevent.
2 For a simple "Vote A or B", intended to bias towards B, perhaps for every 50 instances or so (and only after the first 1000 votes have been cast, even, to allow limited testing to proceed without 'error'?) make the "A" button actually record "vote C". All local queries/printouts at the voting station re-render "voted C" as "voted A", but at the actual collation/counting stage(s) all "vote C" examples are taken as "vote B". hash(Voter1234,VoteC)!=hash(Voter1234,VoteA), of course, but if you're rigging the system this way then you just falsify either voter-end or collator-end hasher the appropriate way to grant apparent consistency.