I think you are protecting against your threat the wrong way, and I think you're also missing out on protecting against some additional threats.
Hashing vs encryption
First and most important: the end user's password should never be encrypted. It should only ever be hashed. Encryption is reversible but hashes aren't. In the event of system breaches, you don't want someone to be able to decrypt an encrypted user password. That could just be a simple matter of accidentally using the wrong terminology: its easy to confuse the two.
The goal
Before jumping in, it helps to reiterate the big picture: what are you trying to do here? You are trying to make it easy for a kiosk to identify a user securely so that they can use a pre-paid account balance.
Breaking it down
The simplest solution would be to simply use the user's unique id to build the QR code. This would get the job done very easily. The problem with that (which your solution is trying to solve), is that the user id is probably guessable, so someone might easily figure out how to build your QR codes and start generating them for random user ids until they find someone with lots of money on their account.
Your use of the three piece identifier is designed to circumvent this problem. The goal is to make it so that only the actual user is able to generate the QR code and use their money. The issue I see is that you have used the user's password in the QR code generation process. This has the benefit of making it hard for anyone other than the user to generate the QR code, but it has a big disadvantage of increasing the "surface area" for the user's password to be stolen. Inherently, the more you use the user's password, and the more it transfers back from client to server (in any form), the more opportunities there are for a malicious user to steal it and use it to break into the actual account. Granted, doing so would require understanding the form of your 3_piece_identifier and then doing a brute-force on the password, but such things are not outside of the realm of possibility, even if it isn't the highest on the list of concerns.
An important attack vector
However, your scenario doesn't protect against a simpler and much easier attack vector: simple replay attacks. Nothing in your scenario ever causes the QR code to change, so if anyone could simply get a picture of the QR code created by the authorized user, that is all that would be necessary to pretend to be them in the future. It could be as simple as literally taking a picture of someone else's phone while they have the QR open (maybe the person standing in front of you in line?) and then opening up that picture from your phone's gallery, and scanning the picture of the QR code when you checkout. Unless the people running the cash register are paying attention (hint: they usually don't), you get to use someone else's balance with little effort.
One possible way to solve all of this
As a result, what you have isn't going to work (I don't think). I think you should not bother using the password as part of the verification, and you need something to protect against replay attacks. It can actually be very simple: when the user loads up the QR code on their phone they can hit up an API server-side to request a one-use key. This will be generated server side, and it can even just be a completely random string: it doesn't have to include the user's email/id/password, but instead is simply associated with that user's account. Make sure you and use a cryptographically secure random number generator, of course. Make it nice and long (as long as it fits well in a QR code), make sure it is unique, store it server side associated with the customer along with an expiration time (no more than a couple minutes even), and then send it down to the client. The client application turns it into a QR code, the employee app scans it, sends it back up, the server verifies that it is valid, that it hasn't expired, and can now bill the client's account properly. As long as the API endpoint that generates the one-use-key requires a logged in user to work, everything should be nice and secure (or at least, as secure as the user's account is). To recap:
- User logs in
- User requests to pay with the account balance
- Client sends up request of single-use-key
- Server generates (via CSPRNG) a unique single-use-key and stores it with the user's account, along with an expiration time
- Server sends single-use-key back down to client
- Client turns single-use-key into QR code
- Employee app scans QR code and converts back to single-use-key
- Employee app sends up single-use-key to server
- Server verifies key's validity and can now charge the proper account
I would also be curious to see what suggestions other's may have.