Webhooks в биткойн-транзакциях - как применить бизнес-логику? - PullRequest
0 голосов
/ 05 октября 2018

Я хочу начать принимать Биткойн на своем сайте.

Чтобы сделать это, я написал следующий фрагмент кода, но я действительно пытаюсь понять, как я могу реализовать правильную бизнес-логику после того, как транзакция будет завершена.

Вот код:

<html>

<head>

    <title>Pay with Bitcoin</title>

    <script>

            //Gets the URL of the Webpage and gets the price value of this transaction in USD.
            //For simplicity Here the Value is passed in the URL.
            //However in production you wanna use POST instead of GET.

            const myUrl = window.location.href;
            const url = new URL(myUrl);
            const usdPrice = url.searchParams.get("price");

            //This is the function where all the magin happens

            const showQR = () => {

                    //URL of the api which will provide us with current BTC exchange rate

                    const apiUrl = "https://blockchain.info/ticker";

                    const hr = new XMLHttpRequest();

                    hr.open('GET', apiUrl, true);

                    hr.onreadystatechange = function(){

                    //Make sure the API sent a valid response

                        if(hr.readyState == 4){

                            let ticker = JSON.parse(hr.responseText);

                            //Get last BTC/USD exchange value from the API , then convert Price from USD to BTC 

                            let BTCprice = ticker.USD.last;

                            let btcToPay = usdPrice / BTCprice;

                            //Make sure you have just 8 decimal points in your BTC price!!

                            btcToPay = btcToPay.toFixed(8);

                            //Use google API (or other...) to create the QR code. Pass on your btc public address and 
                            //the amount (btc price) dynamically created. Message and label parameters can be dynamic too.

                            let qrurl = "https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl=bitcoin:1BAnkZn1qW42uRTyG2sCRN9F5kgtfb5Bci?amount="+btcToPay+"%26label=CarRental%26message=BookingID123456";

                            //Populate the 'btc' DIV with QR code and other info...
                            document.getElementById('btc').innerHTML = "<img src=" +qrurl+"><br> <span class = 'greenMoney'>" + usdPrice + " usd / " + btcToPay + " BTC </span>";

                            }

                    }

                hr.send();

            };

    </script>

</head>

<body onload = "showQR()">

    <h1>Pay with BitCoin</h1>

    <div id = "btc">

    </div>

</body>

</html>

Этот код выполняет следующие действия:

  1. Получает текущий курс доллара США / БТД с помощью API блокчейна.

  2. берет цену в долларах США за URL и преобразует ее в BTC

  3. создает QR-код с помощью Google API.

  4. Встраивает цену, метка и сообщение в QR-код

  5. Отображает QR-код в DIV

Я также настроил службу веб-подключения, которая будетпрослушивать новые транзакции, происходящие в указанном адресе кошелька.Затем производится обратный вызов на мой сервер посредством запроса POST.

Проблема в том, что метка и параметры сообщения, переданные в QR-код, не будут записаны в блокчейне.

Это просто удобная ссылка для клиента, чтобы напомнить ему, за что заплатила определенная транзакция.

В результате обратный вызов на мой сервер практически бесполезен.

ВФактически, обратный вызов не возвращает идентификатор бронирования или любую другую информацию, которая может помочь мне понять, кто за что заплатил.Излишне говорить, что в этом сценарии невозможна бизнес-логика: я не могу обновить статус заказа в своей БД, я не могу отправить подтверждение по электронной почте нужному клиенту.

Как я могу вставить соответствующую информацию (например, идентификатор бронирования) в платеж BTC, в идеале через QR-код?

Если это возможно, как я могу получить эту информацию позже, когда мой серверполучает ответный звонок, сообщающий, что на мой BTC-кошелек была произведена новая оплата?

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

@ Raghav Sood спасибо за ваш вклад, который направил меня в правильном направлении.

Используя NodeJS / Express / MongoDB в бэкэнде, мне удалось реализовать решение, которым я хотел бы поделиться здесь.

Прежде чем начать, я хочу сделать большой отказ от ответственности: это решение не единственное, оно не самое лучшее, оно не самое быстрое и, вероятно, не самое элегантное.

В любом случае, это решение имеет то преимущество, что не полагается на пакетные решения третьих сторон.Это соответствует духу всей философии «без посредников» сообщества биткойнов.Самое важное, что ваш XPub всегда остается на вашем сервере и НЕ используется совместно с какой-либо внешней службой, что, вероятно, является самым мудрым подходом.

Сказав это, можно показать динамические уникальные адреса BTC клиентам:

  1. Прежде всего, я установил счетчик, который отслеживает, сколько адресов btc было создано для клиентов из моего HD-кошелька.

Важно убедиться, что вы никогда не предоставляете клиентам один и тот же адрес дважды, что хорошо для конфиденциальности всех сторон, а также для реализации бизнес-логики в вашем приложении.

Для этого я сохраняю «значение счетчика» в моей БД.Каждый раз, когда кто-то посещает страницу оплаты BTC, это значение извлекается из mongo с помощью функции "dealCount" и присваивается переменной "serialPay", которая равна значению, полученному из Mongo + 1. В бэкэнде код был бычто-то вроде этого:

`function dealCount(){`

        return new Promise(function(resolve, reject){

            Deal.find({_id: "ID_OF_OBJ_WHERE_YOU_STORE_COUNTER"}, function(err, data){

              if(err){

                console.log(err);

              }

                resolve(data[0].serialDeal + 1);

            })

        })

      };

Полученное новое значение (которое позже будет снова сохранено в Mongo для отслеживания созданных адресов) используется для генерации нового публичного адреса BTC для клиента под рукой.,Если вы продолжите читать, вы увидите, как.

Для динамического создания новых публичных адресов требуется ключ xPub его или ее HD-кошелька.Если кто-то кодирует в NodeJS, есть пара библиотек (которые можно импортировать на сервер), которые довольно легко разрешат эту операцию: bitcoinjs-lib и / или bitcore-lib.Лично я выбрал Bitcore-lib, потому что здесь меньше зависимостей, и мне было легче усваивать вспомогательные материалы.

Codewise, генерация адреса происходит следующим образом:

        const bitcore = require('bitcore-lib');

        app.post("/pay.html", urlencodedParser, function(req, res){

        let serialPay = dealCount();

        serialPay.then(function(serialPay){

          const pub = new bitcore.HDPublicKey('INSERT_HERE_YOUR_XPUB_KEY');

          let derivedHdPk = pub.derive('m/0/'+serialPay);

          let derivedPk = derivedHdPk.publicKey;

          let myDynAddress = new bitcore.Address(derivedPk);

          res.render('pay', {myDynAddress: myDynAddress});

        });

      });

Затем, используя EJS в качестве движка шаблонов, я мог бы легко сделать динамический адрес полученного биткойна во внешнем интерфейсе (/pay.ejs):

let myDynAddress = "<%=myDynAddress%>";
let qrurl = "https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl=bitcoin:"+myDynAddress+"?amount="+btcToPay+"%26label=CarRental";

Это сгенерирует QRКод динамически.В оригинальном вопросе можно увидеть, как сделать это на веб-странице.В то же время следует также ввести функцию для хранения обновленного счетчика «serialPay» обратно в БД.

На этом этапе следует начинать мониторинг только входящих (неподтвержденных) платежей по сгенерированному динамическому адресу BTC.Простой способ сделать это - использовать API веб-сокета blockchain.info.Когда приходит платеж, все идет вперед, как предлагает @Raghav Sood: один проверяет входящую транзакцию, проверяя, правильно ли клиент заплатил нужную сумму по нужному адресу.

Теперь вы знаете, кто за что заплатил, и может быть задействована всякая бизнес-логика.

0 голосов
/ 05 октября 2018

Короче говоря, вы не можете.

При приеме платежей вы должны указывать каждому счету новый адрес BTC.Таким образом, когда вы получаете уведомление о входящей транзакции, вы можете проверить адрес получателя, чтобы увидеть, какой счет оплачивается, и сравнить полученную сумму с ожидаемой суммой.

Примечание

Технически, вы можете встраивать такие вещи, как идентификатор заказа, в OP_RETURN.Однако большинство кошельков не поддерживают такие транзакции, и любые пользователи, которые хотят платить вам с биржевого счета, не смогут это выполнить.

...