How to process Bitcoin payments cheaply and easily

Tuesday, 26 November, Year 5 d.Tr. | Author: Mircea Popescu

Step 1. Acquire a Bitcoin address. This may be through a web wallet you trust, or through running a copy of the Bitcoin code on a system you controli or even by creating a paper wallet or in any other way. Let us suppose this is 1YourBitcoinAddress89855.

Step 2. On the webserver where you intend to offer visitors the option to purchase with Bitcoin, include a php script looking something like the following :


if (filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {

  $email_hash = hexdec(substr(md5($_POST["email"]."salt"),3ii,4)) %10000;

  if ($_POST["credits"] > 10000) {
    $cost = $_POST["credits"]/1000000 + $email_hash / 100000000;
    $crd = $_POST["credits"];
  } else {
    $cost = 0.01 + $email_hash / 100000000;
    $crd = 10000;

  $message = wordwrap("Hello!\r\n\r\nYou have ordered ".$crd." Trilema
    credits. Please send exactly ".$cost." BTC to
    1YourBitcoinAddress89855 .\r\n\r\nUpon receipt of your payment you
    will receive a further email to this address containing your
    password and instructions on accessing Trilema.\r\n\r\nThank you
    very much for your support!",70, "\r\n");

  mail($_POST["email"], 'Subject', $message, 'From:'."\r\n".'Reply-To:');
  mail("", "Subject", $_POST["email"]." ".$cost." ".
    $crd." ". $_SERVER['REMOTE_ADDR'], 'From:'.


header( 'Location:' ) ;


You will have to change the red bold parts to reflect your own circumstances ; use your own email address and domain name for redirection, and also create your own secret salt.iii You will probably also want to change the message to something reasonable for your own circumstances : if you're selling game gold you won't likely wish to be talking about Trilema credits.

You will obviously need to pass various numbers through to the email, such as the customer's total order value. Make sure however you do not pass strings, as such, or else your entire sales page may become an open mail relay.iv

This script assumes you are selling something like Trilema credits : a fungible item of which users are expected to buy at least 10k units at a time, with no upper bound. If you are selling discrete items, slight modifications will be required on the math part, but these shouldn't be too difficult to implement.

Step 3 : add a form on a webpage, where users can order. You can see such a form on the Trilema credits order page (click "show html source" or w/e your browser calls it). There's really nothing to it, just a forum that POSTs to the above described script. You can obviously style it any way you wish. If you add or rename fields, they will all be available in the script as $_POST["name"], which is why the form field called email is referenced by the script as $_POST["email"].

That's pretty much it, you're all done. All you have to do now is watch your Bitcoin addressv for incoming payments, match them against orders in your inboxvi and send delivery as required.

The heart of the entire system is that users will be overcharged up to 9999 satoshi (less than 0.0001 BTC). The number is calculated on the basis of their declared email, by hashing the email + a salt, taking a few digits from that hash, transforming them into a number then taking the remainder from a division with 10`000. This overchage allows you to identify who paid you (as User X is unlikely to know User Y's email, and so if anyone paid the sum corresponding to User Y's email that's probably User Y himself).

This system then has two main vulnerabilities : on one hand, if someone simply sends some random Bitcoin to your address you will be unable to find out who actually sent it. On the other hand if you happen upon a collision (ie, two users who have different emails which just happen to hash to the same exact value) you may end up sending the purchase to the wrong user.

The first problem is easily enough resolved : you can at your option either make prominent notice that any incorrect sums will be kept, and encourage users to send the exact amount indicatedvii, or else you can release Bitcoin to those users that can verify they control the sending address.viii

The second problem is not so easily resolved : collisions are always possible. You can either increase the spaceix or learn to live with it : losing one item out of every 10`000 to goddess Collidia, the daughter of old Bitcoin isn't exactly the worst fate in the world. Alternatively, you may create multiple addresses and rotate them as part of your script workings. This also enlarges the space of collisions, at no cost to the customers but at a cost to you, as there'll be more Bitcoin addresses you need to keep an eye on for incoming payments. In the end, whichever of the three avenues makes more sense (eat the cost outright, pass the cost down to the customer or eat the cost through application of technology) is your own business decision.

There will be those who will claim this system is "not good", chiefly proceeding on the grounds that "you should never reuse Bitcoin addresses". This is mostly a myth, borne out of partial understanding of what Bitcoin is and what Bitcoin does in the early days of 2011ish. In practice Bitcoin is many things to many people, and the only Bitcoin public company worth the mention (MPEx) has been reusing its addresses for years now. It's a little difficult to argue with actual experience on the basis of "some nonsense I heard someone once say".

It is certainly possible to generate a Bitcoin address for each customer or for each transaction - BitBet for instance uses such a system. This approach requires a larger technological investment on the part of the merchant, and for this reason is not adequate for all situations. If all you're going to do is sell a few hundred items over a Bitcoin sort of etsy or ebay, something as described above, that you can implement by yourself over an afternoon and maintain by yourself at the cost of five minutes a month is much better a solution than something you will have to hire outside help for - you likely don't have the means to vet outside help, and in Bitcoin business that is a major liability.

It is also certainly possible to use a dedicated "payment processor" company, such as the recently defunct BIPS. If you are happy with paying their fees and undertaking the implicit counterparty risk, that may work well for you. Perhaps you may find a processor that doesn't disappear with your funds like BIPS did, and that doesn't make a complete mockery of your ordering system like WalletBit did with Avalon's 2nd batch. Or perhaps you find a processor that actually delivers services you want or need in exchange for these costs and risks.

Notwithstanding all these considerations, the described solution is by far the best available to the small merchant looking to offer Bitcoin payment over the web.

Final note : The process herein described is protected as patent pending, which means you may not claim you have invented it. That aside, the process is offered freely for use by any party for any purpose.

  1. This should be in your physical control, a machine running silently in a locked cabined somewhere inconspicuous or such. Under no circumstances should this be happening on the same physical machine that hosts your web store / web pages. []
  2. The resulting hash is 32 characters long. You want 4 of these by default. Consequently any value between 1 and 28 (inclusive) works for our purposes. If you modify that 4, to eat more or less then you should also modify the % 10000 accordingly. []
  3. A salt is a string of characters that is added to a plain text before hashing, with the goal of preventing a hacker from guessing the plaintext by looking at the hash. For instance : if your email is known to be, then the md5 of your email is also known to be bb434e2d3fad2893ee3a08f2ee0b4385, and should a hacker suspect it may be your email that's hashed he could just check for bb43etc and make sure. However, if instead of simply hashing the email you hash the email plus a secret salt, this avenue of attack is considerably narrowed. It all depends on the quality of your salt, so use a long, random string. Don't worry about remembering it : you don't have to. []
  4. On the subject of spam : it is true you are sending two emails from this script.

    One is sent to your own email address (and perhaps should be directed to a dedicated inbox to allow you to track new orders). The other is sent on an email which belongs to your "customer", which is to say any random person may paste any random email into your webpage form.

    You may not treat these emails as your newsletter subscriber list, because they aren't. While it's perfectly fine to send one email through this process (after all, every account-making script on the web does exactly that, sending a confirmation link by email to arbitrary email addresses random people pasted into a webform), do not allow the email thus sent to contain random text the originating user may control.

    Just to be on the safe side you may wish to implement rate control - but this is an iffy issue as it may block legitimate customers who wish to make multiple orders in the same interval for legitimate reasons. Consequently this matter is left to your own policies. []

  5. For instance through's free service, or by running bitcoind on your dedicated bitcoind system, or through any other means you find convenient. []
  6. Probably best way would be to search by the last 4 digits of a payment. []
  7. Which would be a good thing to do, it's important to start educating users to use Bitcoin correctly, rather than as some sort of space age USD. []
  8. Which can be trivially done by signing a prepared message with that address. []
  9. By overcharging five digits, rather than four, say. This may work well on higher ticket items, but may be impractical if you sell cheap stuff. []
Category: Bitcoin
Comments feed : RSS 2.0. Leave your own comment below, or send a trackback.

4 Responses

  1. Cute system though I don't feel like using it for myself.

    Assuming you don't care about blockchain data mining or shitty services who cooperate with governments, using new addresses each time also adds a security layer over ECDSA, as the public key isn't yet known (the address is only the hash of the public key!).

    Do note that with BIP32 you could easily give a new address each time without much added complexity on both the mail script and on the transaction processing.

    I don't know what BIPS did, but why in the hell a payment processor kept that much money? They should at least send everything to their customers once a day. Why don't those businesses treat their customers bitcoins as scary things they shouldn't have?

  2. Mircea Popescu`s avatar
    Mircea Popescu 
    Wednesday, 27 November 2013

    Because they have no fucking clue, to answer that last question.

    Indeed these basics could easily be improved upon, by anyone so inclined. The idea was to offer an easily digestible entry point, I imagine many people need that as things stand right now.

    It's entirely unclear what privacy disadvantage sharing your address entails, if one for instance mails things.

  3. The Bitcoin price has fluctuated wildly, hitting $230 in April 2013, falling below $70 in July, and then exceeding $600 in November, prompting talk of a bubble.

  1. [...] Senetic The Bitcoin price has fluctuated wildly, hitting $230 in April 2013, falling... [...]

Add your cents! »
    If this is your first comment, it will wait to be approved. This usually takes a few hours. Subsequent comments are not delayed.