Coin Tunnel
Search…
Receiving Data
Detect when a user has paid

Intro

There are many ways of detecting when a buyer pays. The three main ones are using a callback server, constantly polling the API for the transaction, or using the SSE method.

Using a callback server

When you use a callback server, you first of all, must have a server (wow). It must either have a static IP address or a web address. When you create the transaction, specify the server in the "callback" parameter.
You can learn more about this here
The data sent to it will be something like this
{
status: "paid",
txid: "txid",
note: "note in any format",
buyerId: "buyer id", // this is swapped often
creation: 1621310467272,
expiry: 162131099999,
price_in_crypto: 4,
price_in_usd: 400,
coin:"ltc",
version: "v2",
crypto_network_txid: "the crypto network txid",
timeStamp: Date.now(),
archived: true
}

Constantly polling the API server

This is the most inefficient way of doing this, and may cause you to be rate-limited. You WILL NOT get real time updates, and you will only get updates when YOU poll the server. As you can imagine, this probably requires a for loop. The best endpoint to use is this one.
You will get something like this every time you poll the server if the buyer has paid.
{
"status": "ok",
"payment-status": "payment received",
"data": {
"status": "Success!",
"merchant": 77520157,
"directLogs": {
"network": "BTC",
"txid": "3c68b2069621640294faf01008aa98c881a0ed62da76558a2659eee2f0e3c18b"
},
"txid": "3evs8e4pb1lzfz75sje0s2gep32b71mfglt",
"note": {
"item": "computer",
"id": "123456"
},
"buyerId": "46h80omkgvwa21j1k46g66j8r",
"creation": 1619302325317,
"expiry": 1619302504844,
"price_in_btc": 0.000747,
"price_in_usd": 20,
"archived": true,
"timeStamp": 1619302338387
}
}

The SSE method

The mysterious SSE method. So what is it? Well it's a bit like websockets, the only difference is that it's wayyyy more efficient for the server. This allows us to extend the timeout period from 10 minutes to 1 hour. This only works for API v2, so transactions that are created with API v1 will not be sent. Use the below endpoint to access it
get
https://www.coin-tunnel.ml/api
/v2/transactions/sse/:apikey
SSE method
There are 4 types of responses. One type is the initialization message, which just returns the api key that you used. The second type of mesasge is a connection message, which tells you if your connection is ok. The third type of message is the heartbeat message, which is to prevent the SSE connection from closing, and also is a way for you to detect if the connection has been closed, and re-open one if it has been. The final type is payment-status responses, which are structured exactly the same as normal callback responses.
To get started, use this npm package like this
const apikey = "your api key"
var eventsource = require("eventsource");
const { performance } = require('perf_hooks');
var source = new eventsource('https://www.coin-tunnel.ml/api/v2/transactions/sse/'+apikey);
var previousHB = 0;
var exit = false;
checkTimeout();
checkMessages();
async function checkMessages() {
source.onmessage = function(event) {
let data = JSON.parse(event.data);
if (data.heartbeat) {
previousHB = performance.now();
}
// do something with the data;
console.log(data)
};
await checkExit();
return;
async function checkExit() {
while (true) {
await sleep(1000)
if (exit === true) return;
}
}
}
async function checkTimeout() {
while (true) {
//
await sleep(1000)
if (performance.now() - previousHB > 5000) {
console.log("Could not contact SSE server! Connection closed? Attempting to reconnect...");
source.close();
await sleep(1000)
source = new eventsource('https://www.coin-tunnel.ml/api/v2/transactions/sse/'+apikey);
exit = true;
checkMessages();
}
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
This code has built in error checking and detects if the connection has closed or something went wrong. It will attempt to reconnect every 2 seconds after that.