Проверка лицензионных ключей из приложения на Node или Go: лимит устройств, срок действия и отзыв
Когда Skalp генерирует лицензионный ключ на каждую продажу, приложение проверяет его одним запросом к API. Ответ говорит, работает ли ключ, а если нет, то почему: истёк, отозван после возврата, превысил лимит устройств или привязан к закончившейся подписке. Ниже настройка и код для Node, Go и обычного HTTP.
Настройка товара
- Создайте товар и выберите выдачу лицензионного ключа. Тогда каждый заказ получает новый ключ.
- Задайте лимит устройств, если ключ должен работать только на нескольких компьютерах, и срок действия, если лицензия должна истекать через заданное число дней. Оставьте срок пустым для бессрочной лицензии или продавайте товар по подписке, чтобы ключ работал, пока план оплачен.
- Создайте API-ключ только с областью
licenses:validate. С одной этой областью ключ не может читать заказы и ничего не меняет, поэтому его можно встроить в приложение.
Node
import { Skalp } from '@skalpgg/sdk'
const skalp = new Skalp({ apiKey: LICENSE_CHECK_KEY })
const result = await skalp.licenses.validate({
key: enteredKey,
hardwareId: machineId,
})
if (!result.valid) {
showError(result.message)
} else {
unlock(result.license?.expiresAt)
}
Пакет работает на Node 20+, Bun, Deno и edge-средах. В браузере с API-ключом он отказывается запускаться, если не передать dangerouslyAllowBrowser: true, поэтому проверка для веб-страницы должна идти на Вашем сервере.
Go
client := skalp.New(skalp.Options{APIKey: licenseCheckKey})
res, err := client.ValidateLicense(ctx, skalp.ValidateLicenseParams{
Key: enteredKey,
HardwareID: machineID,
})
if err != nil {
return err
}
if !res.Valid {
return fmt.Errorf("license: %s", res.Message)
}
Любой другой язык
curl https://api.skalp.gg/v1/licenses/validate \
-H "x-api-key: $SKALP_LICENSE_CHECK_KEY" \
-H "content-type: application/json" \
-d '{"key":"THE-BUYERS-KEY","hardwareId":"9f2c41..."}'
Добавьте в тело "productId", если ключ от другого Вашего товара не должен разблокировать этот.
Что значат коды
| Код | Значение |
VALID | Ключ работает. В ответе есть ещё дата окончания и число занятых устройств. |
NOT_FOUND | В Вашем магазине нет такого ключа. |
PRODUCT_MISMATCH | Ключ принадлежит другому товару, а не переданному productId. |
LICENSING_DISABLED | У товара не выбрана выдача лицензионного ключа. |
REVOKED | По заказу сделан возврат или проигран чарджбэк. |
SUSPENDED | Лицензия приостановлена. |
EXPIRED | Срок действия лицензии истёк. |
SUBSCRIPTION_INACTIVE | Подписка, к которой привязан ключ, закончилась. |
DEVICE_LIMIT_REACHED | Ключ уже привязан к стольким компьютерам, сколько разрешает товар. |
Лимит устройств
Если Вы передаёте hardwareId, а у товара есть лимит устройств, первая проверка с нового компьютера привязывает его к ключу. Проверки с привязанных компьютеров проходят, а новый компьютер сверх лимита получает DEVICE_LIMIT_REACHED. Передавайте значение, которое не меняется на одном компьютере, и сначала хешируйте его, чтобы сырые данные о железе не покидали компьютер. Когда покупатель меняет ПК, Ваш сервер может освободить места через licenses.resetDevices. Этому вызову нужна область licenses:write, поэтому в самом приложении ему не место.
Работа без сети
Проверяйте ключ при запуске приложения и сохраняйте последний успешный ответ с отметкой времени. Без сети принимайте сохранённый ответ в течение выбранного Вами льготного периода, например нескольких дней, и проверяйте снова, когда приложение снова в сети. Ключ, отозванный за это время, не пройдёт эту проверку.
Своя копия ключей
Если удобнее проверять ключи в своём бэкенде, берите их из вебхука order.paid, в котором есть лицензии заказа. Вебхуки о возвратах и спорах подскажут, когда отключить ключ. Вебхуки и API.
Частые вопросы
Безопасно ли встраивать API-ключ в десктопное приложение?
Только ключ с единственной областью licenses:validate. Он умеет проверять ключи и больше ничего.
Может ли покупатель перенести лицензию на новый компьютер?
Да, после того как Вы освободите его устройства через licenses.resetDevices со своего сервера или из инструмента поддержки.
Что происходит с ключом, когда подписка заканчивается?
С этого момента проверка возвращает SUBSCRIPTION_INACTIVE.
Обязательно ли использовать SDK?
Нет. Проверка это один POST-запрос по HTTPS с телом в JSON, так что подойдёт любой язык, который умеет отправлять запросы.