We accept payment in bitcoin: Part four, closer to the point!

We accept payment in bitcoin: Part four, closer to the point!

In previous articles, we looked at the general principles of organizing a bitcoin payment gateway, figured out the tools and necessary software, and even assembled our own pocket bitcoin network.

To understand the next steps, it is advisable to have at least a basic understanding of what JSON is and how the http protocol works. 

In short, JSON (JavaScript Object Notation) is a simple format that allows you to transmit heterogeneous data in the form of plain text. It is important that JSON allows you not only to transfer data, but also to restore its structure. Initially (as you can easily guess from the name) it was proposed for the JavaScript language, but due to its simplicity it became quite widespread. It is interesting to us primarily because this is the form of data that is used when exchanging information between our code and bitcoind.

I will not give examples of finished code. Different programming languages ​​are now used for web development, and describing examples in each of them is beyond the scope and scope of our series of articles. Instead, I will show the result of the execution using curl - a unix/linux command line utility. In case it is impossible to do without an example, I will use pseudocode.

The most important thing we need to understand now is how we can interact with the bitcoind server and how we can perform the important and most critical tasks to get a working payment gateway.

First, let's try to get information about the state of the node, but not with the bitcoin-cli getwalletinfo command, as we did before, but using an RPC request. Let's run the following command:

curl --data-binary '{"jsonrpc":"1.0","method":"getwalletinfo","params":[]}' http://username:userpassword@localhost:18332

In this command we pass the generated JSON request. Actually the call itself: "method":"getwalletinfo". This request is sent as a regular http request to the address localhost:18332 - that is, our local machine, and the RPC port that we specified when configuring the test network. And username:userpassword - correspond to the rpcuser and rpcpassword parameters that we specified in the same configuration file. As a result, we will get something like this:

{
  "result": {
    "walletname": "wallet.dat",
    "walletversion": 159900,
    "balance": 14717.18723440,
    "unconfirmed_balance": 0.00000000,
    "immature_balance": 78.12526560,
    "txcount": 1002,
    "keypoololdest": 1528970690,
    "keypoolsize": 999,
    "keypoolsize_hd_internal": 1000,
    "paytxfee": 0..00000000,
    "hdmasterkeyid": "be875fb1dc27d408a5c032d8714cf21cbc3b9af0"
  },
  "error": null,
  "id": null
}

The first step to receive payment using bitcoin (like most cryptocurrencies) is to obtain a new unique address, which will also serve as a payment identifier. This is exactly what we did when we ran the bitcoin-cli getnewaddress command. In fact, this command has additional parameters, but we are not interested in them now. Let's try to do this again (it is assumed that you have bitcoind installed and a test one is configured, as described in previous articles in the series)

bitcoin-cli getnewaddress

2N49FdQ7Ppb1W8BXfNYUPT4BcnWu5B4zFVt

Now we need to do the same thing, but using JSON-RPC. The request itself will have the same form as in the previous example, only instead of "method":"getwalletinfo" we will specify "method":"getnewaddress":

curl --data-binary \
  '{"jsonrpc":"1.0","method":"getnewaddress","params":[]}' \
  http://username:userpassword@localhost:18332

And the result will be accordingly:

{
  "result": "2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF",
  "error": null,
  "id": null
}

If we look closely at the structure of the response, we will see common elements in both cases:

{
  "result": ... ,
  "error": null,
  "id": null
}

The result field contains the result of the request, and error - accordingly, a description of the error if the request could not be completed. Since we have done everything correctly so far, we have never observed that this field was other than empty (null). But the reality is not so cloudless, so when parsing the response from the server, this field should always be checked for errors, and only then proceed to processing the result.

Let's return to our new address.

So, we know how to get a new address, and this can be done in unlimited quantities (well, within the framework of human life, that’s for sure). What, exactly, should we do with it next? When creating a payment form for a client, you give him this address, indicating the amount that needs to be transferred to him. You save the address itself in a safe place, indicating which order it applies to and which user it applies to. Now let’s leave aside interface implementation issues - such as the QR code, magic buttons like “Pay via Bitcoin wallet”, now it’s important for us to master the principle itself..

After receiving the address, we need to understand when the client made the payment. One of the simplest and most obvious ways is to regularly check whether funds have been received or not. Of course, we can do this via getwalletinfo - but this command will show us the general state of our wallet and will not indicate in any way who exactly made the payment. If your store operates half manually, and you receive orders several times a day, and your customers need you more than you need them, you can ask the client for a bitcoin transaction number after payment. 

But this, firstly, is inconvenient, and secondly, it does not solve the problem completely. But let’s assume you chose this option. The user claims to have paid and provides you with a transaction number:

ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b

You can use a public block explorer like blockchain.info, but that's clearly not what we're doing here. Only bitcoind, only hardcore. Let's try to check the transaction ourselves using the command line:

bitcoin-cli gettransaction ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b

In response, we will receive something like this (if the transaction, of course, really exists and took place over the network):

{
  "amount": 0.00000000,
  "fee": -0.00007880,
  "confirmations": 0,
  "trusted": true,
  "txid": "ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b",
  "walletconflicts": [
  ],
  "time": 1529143485,
  "timereceived": 1529143485,
  "bip125-replaceable": "no",
  "details": [
    {
      "account": "",
      "address": "2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF",
      "category": "send",
      "amount": -10.00000000,
      "label": "",
      "vout": 0,
      "fee": -0.00007880,
      "abandoned": false
    },
    {
      "account": "",
      "address": "2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF",
      "category": "receive",
      "amount": 10.00000000,
      "label": "",
      "vout": 0
    }
  ],
  "hex": "02000000.....12bf2ed000e9030000"
}

I've removed some of the information to make it easier to read, but overall this is exactly what we'll get in response. Firstly, you will always need to pay attention to the confirmations parameter; it indicates whether the transaction is included in the block, that is, whether it is confirmed. In Bitcoin, it is generally accepted that a transaction is confirmed after 6 confirmations, but recently they are often limited to 3 or even one confirmation. The second thing we need to pay attention to is the details list, it shows all the inputs and outputs of the transaction. We are interested in blocks that contain category": "receive . This is logical, we expect payment.. And in these blocks we must already find the address that we gave to the client and compare the amount he sent. We have much more information, but this is exactly the information that interests us in the first place.

Let's do the same thing, but using an RPC request:

curl --data-binary \
	'{"jsonrpc":"1.0","method":"gettransaction","params":["ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b"]}' \
	http://username:userpassword@localhost:18332

I will not duplicate the answer, it is completely identical to the one received using the command line. But in the request itself we have something new. Pay attention to the "params" block. It stopped being empty. Instead, we have a transaction number in it. When making RPC requests, remember that the order of the parameters matters because they are not named. We will need it in the next example.

Of course, asking the user for a transaction number is not fashionable, inconvenient and in general. And we will have to deal with the fact of payment ourselves. We do not know if there was payment and if so, when. All we have to do, as I said above, is to check the status of the address once a minute.

bitcoin-cli getreceivedbyaddress 2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF

Note to the owner: when requesting, by default in the response we will only see funds that have already been confirmed. If we want to see the fact of an unconfirmed payment, then we need to add 0 to the end of the command.

If we want to see what amount has, for example, at least 6 confirmations, then accordingly we need to add 6. That is, we indicate the minimum number of confirmations that interests us. Let's try to execute the same request, but in the form of an RPC request.

curl --data-binary \
 '{"jsonrpc":"1.0","method":"getreceivedbyaddress","params":["2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF", 0]}' \
  http://username:userpassword@localhost:18332

And we will see a result similar to the following:

{
  "result": 10.00000000,
  "error": null,
  "id": null
}

We see that some kind person transferred us 10 bitcoins. But since we specified the second parameter 0 in the request, we do not know whether they have confirmations. You can change this parameter, for example, to 1 and repeat the request. We will assume that this is homework, and you can handle it on your own.

We haven't received too much information, and it may raise questions. For example, we don’t know the year the payment was made. The user could, for example, pay not with one payment, but with several.. In general, I would like to receive more information. Okay, for this, instead of getreceivedbyaddress we can use listreceivedbyaddress.

curl --data-binary '{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[]}' http://username:userpassword@localhost:18332

This command will return all payments to all of our issued addresses with transaction numbers.

{
  "result": [
    {
      "address": "...",
      "account": "",
      "amount": ...,
      "confirmations": 7,
      "label": "",
      "txids": [
        "..."
      ]
    },
    {
      "address": "2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF",
      "account": "",
      "amount": 10.00000000,
      "confirmations": 6,
      "label": "",
      "txids": [
        "ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b"
      ]
    }
  ],
  "error": null,
  "id": null
}

And already among this data we will need to find all our addresses and find out who transferred us and how much. It's important to remember that by default, listreceivedbyaddress will only return confirmed transactions to you. If you want to get the full list, then you need to pass 0 as a parameter - just like in the case of getreceivedbyaddress

Using this method becomes more and more difficult and expensive over time - because you see all the transactions with all the addresses that you have.


In general, we have everything we need to accept payments using bitcoin. Of course, the described method is not the most convenient, but nevertheless it already allows you to organize a simple payment gateway.


Read also: WE ACCEPT PAYMENT IN BITCOIN: PART ONE, THEORETICAL

                          WE ACCEPT PAYMENT IN BITCOIN: PART TWO. TOOLS AND PREPARATION

                         ACCEPT PAYMENT IN BITCOIN: PART THREE, YOUR TESTNET. WITH BLACKJACK

                            

You May Also Like

02018-06-15

We accept payment in bitcoin: Part Three, our testnet. With blackjack

In the last article, I told you how to install bitcoind (at least on Ubuntu Linux) and how to connect to testnet. But testnet is a good solution when you conduct tests on a ready-made website that has already been deployed on a server on the Internet. But for local development this is far from the most convenient solution.

Development
22018-06-07

Apple publishes new rules on cryptocurrency apps

According to TechCrunch, a number of Apple developers recently joined forces to create the “Developers Union.” The union asked Apple to provide Apple Store users with the opportunity to download free trials of their applications. This is one of the first times that independent iOS developers are trying to fight back against Apple Store policies.

Development

Latest articles from Development category

Fresh video on our Channel