Оплата в один клик с Minter Link
Tags: minter, cryptography, extension, payment
Published: 2020-09-25 14:02:35

Оплата товаров, услуг или любых действий на вашем сайте в один клик при помощи криптовалюты Minter. Без переключения в консоль, без необходимости вспоминать seed-фразу, без необходимости вводить что-либо в payload. 

Эта статья рассматривает оплату c использованием Minter блокчейна: безопасный способ оплатить что угодно на сайте в один клик при помощи расширения Minter Link.

![Minter Link Payment Flow](https://dev-to-uploads.s3.amazonaws.com/i/48ep5q5zemdg15qry9up.gif)

## Как это работает
Основная идея в том, что Minter Link позволяет упростить процесс оплаты для пользователя. Не нужно вводить точную сумму, не нужно вписывать payload, весь процесс упрощен до нажатия одной кнопки: "Оплатить" или "Отказаться". Рассмотрим процесс по шагам.

### Браузерное расширение Minter Link
**Minter Link** — это браузерное расширение, доступное для [Google Chrome](https://chrome.google.com/webstore/detail/minter-link/clnbjajcehaehmnkihhkcfdpgahdpghj). Основная функция расширения — мультикошелек для Minter блокчейна. После установки вы получаете возможность управлять кошельками, отправлять и получать монеты в сети Minter.

Но Minter Link, помимо этого, позволяет взаимодействовать со страницами, которые вы просматриваете в браузере. Разработчики сайтов могут получать мгновенные обновление от вашего кошелька (если вы дали такое разрешение) и делать запросы на оплату и цифровую подпись сообщений. Для этого существует библиотека Minter Connect.

### JavaScript библиотека Minter Connect
[Minter Connect](https://github.com/minterscan/minter_connect) — это мостик между вашим приложением и браузерным расширением Minter Link. Библиотека, с одной стороны, позволяет получать данные о статусе расширения и данные о публичном адресе, с другой — позволяет запрашивать у пользователя разрешение на доступ к публичному адресу, криптографическую подпись и делать запросы на отправку транзакций.

Подробнее о том, как пользоваться библиотекой — на странице репозитория на GitHub

### Minter Link Payment Flow

![Minter Link Payment Flow](https://dev-to-uploads.s3.amazonaws.com/i/14sa015vky44ij832hke.png)

#### Шаг нулевой: подготовить БД (back end)
Создадим модели для товаров и заказов. У каждого товара буду поля `price` и `coin`, у заказа — `itemId` и `hash`.

#### Шаг первый: запросить `orderId` (front end)
Сделаем запрос на backend c `itemId` товара, который мы хотим оплатить и получим назад уникальный `orderId` заказа. 

Порядок действия такой:
* проверяем наличие расширения (установлено или нет)
* проверяем статус расширения (разблокировано или нет)
* если кошелек разблокирован — делаем запрос на backend, получаем назад `orderId`

#### Шаг третий: сформировать запрос (front end)
Сформируем `paymentData`, чтобы сделать запрос к расширению: payload (ID заказа), адрес для оплаты, сумму и монету оплаты.

#### Шаг четвертый: отправить запрос на оплату (front end)
Отправим запрос в расширение, куда передадим `paymentData` При успешной оплате получим назад хеш транзакции в блокчейне.

#### Шаг пятый: подготовим обработчик транзакций (back end)
На стороне сервера создадим сервис, который будет слушать все транзакции из блокчейна, нас интересуют транзакции с типом `0x01` (Send) и адресатом — нашим кошельком, который мы указали в четвертом шаге. 

У каждой транзакции мы проверим `payload` и ищем там наш `orderId`. Если транзакция найдена, у нее совпадает адрес, payload, сумма и монета — обновим у заказа `hash`.

### Примеры кода

**HTML**

```html
<!-- Расширение не установлено -->
<p if="!isMinterLinkInstalled">Minter Link is not installed</p>

<!-- Расширение заблокировано -->
<p if="isMinterLinkInstalled && !isMinterLinkUnlocked">Minter Link is locked</p>

<button onclick="pay(1)" if="isMinterLinkInstalled && isMinterLinkUnlocked">Purchase</button>
```

**JavaScript**

```javascript
import MinterConnect, { MinterLinkObservableProps } from 'minter-connect'

let isMinterLinkInstalled = false
let isMinterLinkUnlocked = false
let minterPublicAddress = ''
let isAuthenticated = false

// Устанавливаем соединение с расширением
const minterConnect = new MinterConnect('My awesome application')

// Подписываемся на события
minterConnect.subscribe(MinterLinkObservableProps.IsInstalled, (value) => {
  isMinterLinkInstalled = value
})

minterConnect.subscribe(MinterLinkObservableProps.IsUnlocked, (value) => {
  isMinterLinkUnlocked = value
})

async function pay (itemId) {
  if (!isMinterLinkInstalled) return
  if (!isMinterLinkUnlocked) return

  try {
    const orderId = await api.makeOrder(itemId)
    const paymentData = {
      address: 'Mx...',          // наш адрес для оплаты
      amount: '999',             // цена
      coin: 'BIP',               // монета
      payload: response.data.id  // orderId
    }
    
    await minterConnect.paymentRequest(paymentData)
  } catch (e) {
    console.error(e)
  }
}
```

**Node.JS**

```javascript
async function makeOrder (itemId) {
  const item = await getItemById(itemId)
  const order = new Order({
    itemId,
    price: item.price,
    coin: item.coin
  })

  order.save()

  return order.id
}

// Функция, которая будет перебирать транзакции из блокчейна
async function handleTransaction (transaction) {
  // Тип транзакции должен быть Send
  if (transcation.type !== '0x01') return
  // Адресат должен быть нашим кошельком
  if (transcation.data.to !== 'Mx...') return

  const orderId = transaction.payload.trim()
  const order = await getOrderById(orderId)

  // Несуществующий заказ
  if (!order) return
  // Заказ уже оплачен
  if (order.hash) return
  // Сумма не совпадает
  if (order.price !== tx.data.value) return
  // Монета не совпадает
  if (order.coin !== tx.data.coin) return

  // Все хорошо, это наш заказ!
  order.hash = transaction.hash
  order.save()
  
  // Дальше ваша бизнес логика: отправляем письмо об успешной оплате, начисляем бонусные баллы, уведомляем frontend о смене статуса заказа и т.д.
}

async function getItemById (itemId) {
  return db.getItemById(itemId)
}

async function getOrderById (orderId) {
  return db.getOrderById(orderId)
}
```

### Плюсы и минусы

Это просто, удобно и безопасно. 

* **Повышенная безопасность**. Приватный ключ кошелька хранится в расширении пользователя локально в зашифрованном виде. Атаковать напрямую локальное хранилище очень сложно, у каждого расширения свое изолированное окружение и даже в случае утечки зашифрованной строки с приватным ключом потребуется **очень много ресурсов**, чтобы расшифровать строку, закодированную AES c 256-битным ключом.

* **Упрощенный UX**. Вместо того, чтобы вводить данные карты или копировать данные заказа и затем вводить его у себя в кошельке, пользователю нужно нажать всего одну кнопку. Не нужно ничего запоминать, все "ключи" лежат у него прямо в браузере. 

* **Конфиденциальность**. Все хранится локально, никакие данные не передаются третьим лицам.

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

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

Ничто не мешает вам использовать Minter Link как дополнительный способ оплаты, в дополнение к классическим способам вроде пластиковой карты или мобильных платежей. 

От минусов никуда не деться, серебряной пули не существует. 

* **От пользователя требуется установить Minter Link**. Если аудитория вашего сайта не интересуется криптовалютами и блокчейн-технологиями — скорее всего о Minter они не слышали и вам это не нужно. 

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

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

Спасибо за внимание.

* [Minter Link](https://github.com/minterscan/minter_link)
* [Minter Connect](https://www.npmjs.com/package/minter-connect)
* [Minter Link Playground](https://github.com/minterscan/minter_link_playground) | [Demo](https://minterscan.github.io/minter_link_playground/)

Читайте также: [Логин в один клик при помощи Minter Link](https://dev.to/whitesunset/minter-link-50dp).