You can’t secure a static barcode against copying. It’s not possible.
What you need to protect against this kind of attack is to have the customer enter/scan something dynamic. It has to be changed every time it’s used; it has to change in an unpredictable manner, so that dishonest customers can’t make up a value and fool it; and the back end system must refuse to accept multiple scans of the same code.
One way to do this is to display the QR code on a tablet mounted on the counter. Every time a customer scans it and their app posts a message back to the server, it validates the current code and then changes the QR code to show a new random number to the next customer.
This needs more security, of course. You have to somehow limit your customer records so he can’t just scan 10 barcodes in a row in one minute. You could solve this by only displaying a QR code after the cash register receives payment. Or you could limit the customer record to ignore multiple scans within a 30 minute window.
You could have the cash register print unique barcodes on the receipts, but thieves will pick up discarded receipts from the trash and scan them. It takes sophisticated back end logic to detect this kind of fraud.