Intro

It is a problem we have got a solution for: now you can create invoices with a defined amount and accept Bitcoin payments on these invoices from users.

Prerequisites:

  • Ambisafe Keyserver, configured to work with the currencies of your choice (Bitcoin, in our case)
  • A running web application (we offer libraries for PHP, Ruby, and Python, this guide describes the PHP version)

In the following sections of this article we will walk you through the steps that are required to get a working merchant service, the examples are on PHP but similar code will work for any supported library.

Installation

composer require ambisafe/client

Library initialisation

$client = new Ambisafe\Client('http://keyserver.url:port/', 'application_secret', 'apiKey', 'apiSecret');

Here, the application_secret is a random string, which should be kept secure. It is then used to generate a key which will encrypt the OPERATOR part of the container for multi-sig accounts.

The apiKey and apiSecret are set up in Keyserver, the default ones are demo/demo.

Creating an account

Next, for each invoice you should create a separate account with a unique account ID. We suggest using IDs in the format of the "invoice-{unique_id}", where a unique_id will be a primary key for this invoice in your database:

$account_to_create = new Ambisafe\Account\Simple(['id' => 'invoice-1', 'currency' => 'BTC']);

$account = $client->createAccount($account_to_create);

echo "Created a simple account, address={$account->getAddress()}";

Now you can easily save the account address to your database for future reference and should show it to your user together with the invoiced amount.

Getting account information and balance

If you ever loose the account address you can get it back, knowing your account ID:

$account = $client->getAccount('invoice-1', 'BTC');

echo "Account id={$account->getId()}, address={$account->getAddress()}";

You can also get account balance by using its ID:

$balance = $client->getBalance('invoice-1', 'BTC');

echo "Account BTC balance={$balance}";

Or with the help of its address:

$account = $client->getAccount('invoice-1', 'BTC');

$balance = $client->getBalanceByAddress($account->getAddress(), 'BTC');

echo "Account BTC balance={$balance}";

Receiving payment

However, you do not really need to check the address balance to find if the payment has arrived. After a user sends a payment to the address you have created you will get a callback to the endpoint you have set in Keyserver settings for API key you use (this way you can have multiple applications using different API keys on one Keyserver and getting correct callbacks. Just make sure that account IDs are unique). 

When you receive a callback you should check its account_id/destination, match it with a record in your database, check if received amount is equal to the invoiced amount and then proceed with your business agenda.

Forwarding payment from invoice address

If you decide to stop at the "Receiving payment" step, you will end up with lots of invoice addresses, each containing 0 (if invoice was unpaid) or the invoiced amount. We believe this is not your primary business goal as it is more convenient to gather all this money under one address. To do this, you should create one more address that will be your pool/collector address. You can use your wallet for this currency on some reputable wallet service like Blockchain.info. After receiving a callback you would forward the payment from the invoice address to your wallet in the following way:

$transaction = $client->buildTransaction('invoice-1', 'BTC', 'your_wallet_address', amount_to_send);

$result = $client->submitTransaction('invoice-1', $transaction, 'BTC');

$transaction_hash = $result['transactionHash']; # transaction hash, which you could use to track this transaction

Be aware that if you have received an amount of X BTC, you cannot forward 100% of it to your wallet, because you have to pay a Bitcoin transaction fee, which is set up in Keyserver config as bitcoin.fee_per_kb. So, in the case when you use each invoice address only once (recommended), you have to forward X - bitcoin.fee_per_kb BTC. Note: to overcome this problem, ICAP is used in EToken.