I want to implement payments using Bitcoin without any 3rd party services. I already installed full node on my server and configured RPC API. What should I do next?

Now I plan to work in the following way:

  1. Create wallets for all existing and new users using getaccountaddress method and store address in DB.
  2. Set up an every minute cron job which will calls listtransactions * 1000, loop through transactions to find new which has more than N confirmations.
  3. Store filtered transactions in DB, find user by address and add money to balance.
  4. Send received bitcoins to another (main) wallet using sendfrom method.

I have some doubts about the stability of the solution. I do not think that users will perform more than 1,000 transactions per minute, so when all is working as planned, it looks as pretty stable solution. But what, if, for example, bitcoind (or entire server) will hang / fail / break down? How easy will be to handle payments that were not processed before?

Maybe there is a better way for receiving payments? Thank you.


You should check out walletnotify: everytime a transaction hits your wallet it will fire a command or script off.

Walletnotify will run a shell command everytime something changes in your wallet.

I like this repo.

| improve this answer | |

Create a unique address, log it to a DB with a reference to the user id. The accounts feature was deprecated in 2016

Use the walletnotify feature in your bitcoin.conf instead of a cronjob. This will call a file that can take the transaction id(passed as %s) as an input whenever a new transaction is received in your mempool and again once confirmed. Use the transaction id to find the output address(es), if they match an address in your DB credit that account with the value sent to that output.

Example of passing the transaction id into a GET of "tx"
walletnotify = curl http://mysite.com/newdeposit.php?tx=%s

Example of what your newdeposit.php file could look like

//db connection
$conn = mysqli_connect("localhost", "root", "password", "database_name");
    if (mysqli_connect_errno()){
    echo "Connection to DB failed" . mysqli_connect_error();

//bitcoin node connection
$bitcoin = new Bitcoin("someusername", "somepassword");
$tx = $_GET['tx'];
$tx = mysqli_real_escape_string($conn, $tx);
$getTrans = $bitcoin->gettransaction($tx);
$confirmations = $getTrans["confirmations"];
if($confirmations !== 1){
} else {
//loop through the outputs
    $countDetails = count($getTrans['details']);
    $getAddress = $getTrans['details'][$i]['address'];
    $getReceive = $getTrans['details'][$i]['category'];
        if($getReceive == "receive"){
        $checkAddy = mysqli_query($conn, "SELECT * FROM users WHERE DEPOSIT_ADDRESS = '$getAddress'");
        $doCheckAddy = mysqli_num_rows($checkAddy);
            if($doCheckAddy == 1){
            $amount = $getTrans['details'][$i]['amount'];
            $amount = $amount * 100000000;
            $updateBalance = "UPDATE users SET BALANCE = BALANCE + '$amount' WHERE DEPOSIT_ADDRESS = '$getAddress'";
            $doUpdateBalance = mysqli_query($conn, $updateBalance);

As for re-launching after a crash you could look into using a bash script on a cronjob. I found the below example on bitcointalk


ps auxw | grep bitcoind | grep -v grep > /dev/null

if [ $? != 0 ]
        /bitcoind start > /dev/null

EDIT: It's important to note this is not meant as a hack-proof solution, but a simple example to show how you could approach your solution.

| improve this answer | |

As Web Weave mentioned, definitely check out the walletnotify callback. this is the easiest way.

the only thing that I want to mention tho (without knowing the nitty gritty), is that I don't know if this walletnotify is guaranteed to run, and what error do we get when it doesn't. I suppose it's logged but error-handling on the bitcoind layer isn't very clear.

alternatively, to have a supposedly more robust process, it's possible to scan transactions in every block, and find the relevant ones. you need to write more code in this case, but you are making active calls instead of listening for notifications.

| improve this answer | |

Your Answer

