Новости и события » Экономика » Принимаем оплату в bitcoin: Часть четвертая, ближе к делу!

Принимаем оплату в bitcoin: Часть четвертая, ближе к делу!

Принимаем оплату в bitcoin: Часть четвертая, ближе к делу!

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

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

Для понимания дальнейших шагов, желательно хотя бы базовое представление, что такое JSON и как работает протокол http.

Если говорить коротко - то JSON (JavaScript Object Notation) - это простой формат, позволяющий передать разнородные данные в виде простого текста. Важно, что JSON позволяет не только передать данные, но и восстановить их структуру. Изначально (как несложно догадаться из названия) он был предложен для языка JavaScript, но из-за простоты стал достаточно распространенным. Нам он интересен в первую очередь потому, что именно такой форма данных используется при обмене информацией между нашим кодом и bitcoind.

Я не буду приводить примеры готового кода. Для web-разработки сейчас применяются разные языки программирования, и расписывать примеры на каждом из них выходит за объем и рамки нашего цикла статей. Вместо этого я буду показывать результат выполнения с помощью curl - утилиты командной строки unix/linux. В случае, если без примера будет не обойтись - я буду использовать псевдокод.

Самое важное, что нам сейчас нужно понять - это как мы можем взаимодействовать с сервером bitcoind и как нам выполнить важные и самые критичные задачи для получения работоспособного платежного шлюза.

Для начала попробуем получить информацию о состоянии ноды, но не командой bitcoin-cli getwalletinfo, как мы это делали раньше, а с помощью RPC-запроса. Выполним следующую команду:

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

В этой команде мы передает сформированный JSON-запрос. Собственно сам вызов: "method":"getwalletinfo". Этот запрос передается как обычный http-запрос на адрес localhost:18332 - то есть наша локальная машина, и RPC-порт, который мы указали при конфигурации тестовой сети. А username:userpassword - соответствуют параметрам rpcuser и rpcpassword, которые мы указали в том же файле конфигурации. В результате мы получим что то подобное:

{ "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 }

Первый шаг для получения платежа с помощью bitcoin (как и большинства криптовалют) - это получение нового уникального адреса, который по совместительству будет выполнять функцию идентификатора платежа. Именно это мы делали, когда выполняли команду bitcoin-cli getnewaddress. На самом деле эта команда имеет дополнительные параметры, но сейчас они нам не интересны. Попробуем проделать это еще раз (подразумевается, что у вас есть установленный bitcoind и настроена тестовая есть, как было описано в прошлых статьях цикла)

bitcoin-cli getnewaddress 2N49FdQ7Ppb1W8BXfNYUPT4BcnWu5B4zFVt

Теперь нам нужно проделать то же самое, но с помощью JSON-RPC. Сам запрос будет иметь такоей же вид как и в прошлом примере, только вместо "method":"getwalletinfo" мы укажем "method":"getnewaddress":

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

И результат соответственно будет:

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

Если мы внимательно рассмотрим структуру ответа, то в обоих случаях мы увидим общие элементы:

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

Поле result содержит результат выполнения запроса, а error - соответственно описание ошибки в случае, если запрос выполнить не удалось. Поскольку мы пока все делали правильно, мы ни разу не наблюдали, чтобы это поле было отличным от пустого (null). Но реальность не настолько безоблачна, по этому разбирая ответ от сервера это поле всегда нужно проверять на наличие ошибок, и только потом переходить к обработке результата.

Вернемся к нашему новому адресу.

Итак, мы знаем, каким образом получить новый адрес, причем сделать это можно в неограниченном количестве (ну в рамках человеческой жизни это точно). А что, собственно, с ним делать дальше? Формируя форму оплаты для клиента, вы выдаете ему этот адрес, с указанием суммы, которую на него необходимо перечислить. Сам же адрес вы сохраняете в надежном месте, с указанием к какому именно заказу и какому пользователю он относится. Сейчас оставим в стороне интерфейсные вопросы реализации - такие как qr-код, волшебные кнопочки вроде "Оплатить через кошелек Bitcoin", сейчас нам важно освоить сам принцип.

После получения адреса, нам нужно понять, когда клиент сделал оплату. Один из самых простых и наглядных способов - это регулярно проверять, получены ли средства или нет. Конечно мы можем это сделать через getwalletinfo - но эта команда покажет нам общее состояние нашего кошелька и никак не укажет, кто именно сделал оплату. Если ваш магазин работает наполовину в ручном режиме, а заказы у вас приходят несколько раз в день, и вы нужны вашим клиентам больше, чем они вам - вы можете запрашивать у клиента номер bitcoin-транзакции после оплаты.

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

ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b

Вы можете воспользоваться публичным блокэксплорером, например blockchain.info, но это явно не то, чем мы тут занимаемся. Только bitcoind, только хардкор. Попробуем проверить транзакцию сами, с помощью командной строки:

bitcoin-cli gettransaction ce397d610c0066f1f4f38d532bc527daac3bd6aac25081618be63620d9078c7b

В ответ мы получим нечто подобное (если транзакция конечно реально существует и прошла по сети):

{ "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" }

Я удалил часть информации, чтобы не затруднять чтение, но в целом это именно то, что мы получим в ответ. Во-первых, вам всегда нужно будет обращать внимание на параметр confirmations, он указывает включена ли транзакция в блок, то есть подтверждена ли она. В bitcoin принято считать что транзакция подтверждена после 6 подтверждений, но в последнее время часто ограничиваются 3 и даже одним подтверждением. Второе, на что нам нужно обратить внимание, это список details, в нем видны все входы и выходы транзакции. Нас интересуют блоки, в которых содержится category": "receive. Это логично, мы же ожидаем оплату. И вот в этих блоках мы уже должны найти адрес, который мы выдали клиенту и сравнить сумму, которую он отправил. Информации у нас значительно больше, но это именно та, которая интересует нас в первую очередь.

Проделаем то же самое, но с помощью RPС-запроса:

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

Я не буду дублировать ответ, он полностью идентичен полученному с помощью командной строки. А вот в самом запросе у нас появилось что то новое. Обращаем внимание на блок "params". Он перестал быть пустым. Вместо этого у нас в нем появился номер транзакции. При выполнении RPC запросов помните - порядок параметров имеет значение, поскольку они не именованы. Он же понадобится нам в следующем примере.

Конечно, запрашивать номер транзакции у пользователя - это не модно, неудобно и вообще. И с фактом оплаты нам прийдется разбираться самостоятельно. Мы не знаем, была ли оплата и если была то когда. Нам остается, как я говорил выше - скажем раз в минуту проверять состояние адреса.

bitcoin-cli getreceivedbyaddress 2NBqem3SZijakVD4Cy6ZQTMTZzCPRjNMeKF

Хозяйке на заметку: при запросе по умолчанию в ответе мы увидим только средства, которые уже подтверждены. Если мы хотим посмотреть факт неподтвержденной оплаты, то нам нужно добавить в конец команды 0.

Если же мы хотим посмотреть, какая сумма имеет, например, не менее 6 подтверждений, то соответсвенно нам нужно добавить 6. То есть мы указываем минимальное количество подтверждений, которое нас интересует. Попробуем выполнить тот же запрос, но уже в виде RPC-запроса.

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

И увидим результат, подобный следующему:

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

Мы видим, что какой то добрый человек перечислил нам 10 биткоинов. Но поскольку мы указали в запросе второй параметр 0 - то мы не знаем, есть ли у них подтверждения. Можно изменить этот параметр например на 1 и повторить запрос. Будем считать, что это домашнее задание, и с этим вы вполне справитесь самостоятельно.

Мы получили не слишком много информации, и она может вызывать вопросы. Например мы не знаем, года была оплата. Пользователь мог например оплатить не одним платежом а несколькими. В общем хотелось бы получить больше информации. Хорошо, для этого вместо getreceivedbyaddress мы можем использовать listreceivedbyaddress.

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

Эта команда вернет нам все платежи на все наши выданные адреса с номерами транзакций.

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

И уже среди этих данных нам нужно будет найти все наши адреса и выяснить - кто и сколько нам перечислил. Важно помнить, что по умолчанию listreceivedbyaddress вернет вам только подтвержденные транзакции. Если вы хотите получить полный список, то в качестве параметра нужно передать 0 - все как в случае с getreceivedbyaddress.

Использование этого способа со временем становится все более сложным и затратным - ведь вы видите все операции со всеми адресами, которые у вас есть.

В целом мы получили все необходимое, чтобы принимать платежи с помощью bitcoin. Конечно, описаный способ не самый удобный, но тем не менее он уже позволяет организовать простой платежный шлюз.

ПРИНИМАЕМ ОПЛАТУ В BITCOIN: ЧАСТЬ ВТОРАЯ. ИНСТРУМЕНТЫ И ПОДГОТОВКА

ПРИНИМАЕМ ОПЛАТУ В BITCOIN: ЧАСТЬ ТРЕТЬЯ, СВОЙ TESTNET. С БЛЭКДЖЕКОМ.


Магія східної кухні: особливості та традиції

Магія східної кухні: особливості та традиції

Східна кухня відома різноманіттям ароматів та смаків. Вона заснована на глибоких традиціях, історії та має особливості приготування. Звички формувалися впродовж багатьох століть під впливом різних культур та географічних особливостей. Вони присутні в кожній...

вчера 15:32

Свежие новости Украины на сегодня и последние события в мире экономики и политики, культуры и спорта, технологий, здоровья, происшествий, авто и мото

Вверх