If I wanted to build a vending machine where one could buy a cola paying with bitcoin, is the following scenario the typical way to do it?

  1. Customer approaches the machine, and selects the product (whatever the method - button by the product image, or typing a corresponding numeric ID on a keypad)
  2. Machine generates bitcoin address for this transaction and displays on a screen the address' QR code and alphanumeric representation, and the amount to be paid in bitcoins.
  3. Customer uses their smartphone (or whatever device with bitcoin client) to scan the code, enters the amount and submits the transaction.
  4. Vending machine waits for the expected amount to arrive in the account and
    • delivers the product if the amount is what was expected
    • sends the money back if the amount is not what was expected
    • timeouts if nothing arrives within 2 minutes
    • sends the money back if there were technical issues in delivering the product
  5. To avoid necessity to store the private keys for every successful transaction, the vending machine sends the just collected amount to aggregation address and forgets the temporary address.

3 Answers 3


This sounds good, in broad strokes. There are a couple of things I would watch out for:

  • Refunds can be tricky. People who are using web wallets may not really have their own addresses; the wallet operator has a large pool of addresses and tracks customer balances internally. When the customer wants to make a payment, the operator pays from one of the pool addresses and debits the customer's account. So if you try to send a refund to such a customer, it goes back to the operator's address, but they may not have the ability / motivation to recredit the customer. They might even throw away the private key once the coins are spent (and the change sent to a new pool address), in which case the refunded coins are lost forever. Either way, the customer is bummed. There is some further information at Is there a standard procedure for refunding Bitcoin transactions?, and BIP 70 is a proposed solution (where the customer provides a separate refund address explicitly), but since this involves some out-of-band messages over HTTPS, more infrastructure is needed on the server side.

  • You may want to give up on delivering the product after 2 minutes, but you might not want to give up on the payment. For example, if either your machine or the customer's mobile device has Internet connectivity problems, the payment might be created but not broadcast (or not received by you) until much later. The customer is probably no longer there to get their can of Tab, but you might want to refund their money anyway. So you should keep the private key around. (Actually, there's really no good reason to discard them: if you send the money back to HQ, they normally contain no coins so it's not really a problem if they are stolen, but if somebody sends extra coins to them for some reason, you'd sure like to have them.)

  • Similarly, if you do send a refund, you may want to make sure you spend the same transaction that came in. This will protect you in case the customer tries to double-spend.

  • The payment amount can be embedded in the QR code. This saves the customer a little typing.

  • Quickly sending incoming payments off to HQ for safekeeping is a good idea, but will cost you a fee on each transaction. You could batch them and send them off a couple times a day, or whenever they reach some threshold amount. Alternatively, you could have a system where you generate a bunch of addresses at HQ, keep the private keys there (perhaps even offline), and just give the machine the addresses. (BIP 32 provides a fancier way to achieve that.) The machine can still detect incoming payments, but if a refund is needed, it would have to send a request back to HQ.

  • These are some really good points, thank you. I guess there could always be some rare situations when coins are collected but the product not given and/or coins are not collected but the product is taken, that is technically unavoidable. The goal would be to push that probability as low as possible. After all, also cash-based vending machines sometimes screw up, and there is some human-handled fallback procedure to solve that.
    – Passiday
    Commented Aug 29, 2014 at 20:49
  • 3
    For the description of a complete vending machine we built for research you might want to see tik.ee.ethz.ch/file/848064fa2e80f88a57aef43d7d5956c6/…
    – cdecker
    Commented Aug 31, 2014 at 9:59
  • If you have a camera on your vending machine, it could request a refund address in the case of technical issues which the customer could provide by showing a QR code with his address.
    – Murch
    Commented Sep 7, 2014 at 8:18

That sounds reasonable. I would add that since you'll most likely want to accept unconfirmed transactions, it would be also good practice to check with a list of trusted nodes (such as large mining pools) if they received the transaction. This doesn't entirely remove the risk of a double-spend, but it mitigates it.

  • Is there a list of "large mining pools" available online? :) And how would you check that node has this transaction? Wait for "inv" message from each one?
    – amaclin
    Commented Aug 29, 2014 at 19:03
  • That's a good point, that there should be some measure to guard against double spending. I am not sure how to implement such, though. I guess there is some method the community has agreed on that provides a reasonable assurance.
    – Passiday
    Commented Aug 29, 2014 at 20:34

As a precaution, I think you should never dispose the temporary addresses. Maybe keep them in a database, because you never know when someone may accidentally send bitcoins to the same address again.

  • Well, yes, to protect a silly customer from some random folly. Ie, the shopkeeper also would turn down absent-minded customer's cash, if he comes back in store and says "sorry I think I didn't pay". But perhaps not forever, that should not be the seller's responsibility.
    – Passiday
    Commented Aug 29, 2014 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.