- Сообщения
- 8,673
- Репутация
- 2,486
"Лучшие идеи обычно рождаются из потребностей одного человека" ©
С недавнего времени я всерьёз задумался над тем, что раньше для меня казалось немыслимо - продавать свои программы.
Но как оказалось, это довольно непростое и кропотливое занятие.
В конце этой статьи есть относительно простой вариант реализации данной задумки, но вариант представленный ниже, мне кажется более надёжным и интересным.
Что для этого нужно?
[list type=decimal]
[*]Свой сервер (хранение базы данных, исполнение php скриптов)
[*]Свой сайт (для размещения своих продуктов на продажу)
[*]Регистрация систем электронных денег (WebMoney, PayPal, Yandex.Money, и т.п.)
[*]Регистрация в платёжной системе (в данной статье рассматривается http://digiseller.ru - для упрощения процедуры продажи продукта)
[*]Хорошая программа с уникальным функционалом
[*]Энтузиазм и маркетинговые способности
[*]Свободное время (много)
[/list]
Теперь собственно разберём по частям, что требуется сделать:
- Сервер -
[list type=upper-roman]
[*]На сервере создаём базу данных, допустим назовём её MySoft.
[*]Далее на сервер нужно загрузить два php скрипта:
[/list]
- Сайт -
[list type=upper-roman]
[*]Тут ничего сложного, создаёте свой сайт, где будет размещаться интернет магазин с вашими продуктами (такую возможность предоставляет сервис digiseller).
[/list]
- Системы электронных денег -
[list type=upper-roman]
[*]Регистрируете электронные деньги, такие как WebMoney, PayPal, Yandex.Money и другие. Стоит отметить, что при регистрации лучше сразу заполнять все данные и получать нужные сертификаты (см. справку для каждой платёжной системы отдельно), позже это упростит всю процедуру получения средств.
[/list]
- Платёжная система (digiseller) -
[list type=upper-roman]
[*]Регистрируетесь, создаёте свой магазин, получаете код для вставки на своём сайте (можно вставить на любой странице - это и будет страница вашего интернет магазина).
[*]Далее создаёте категорию своего ПО, и добавляете товар, где...
[list type=lower-alpha]
[*]Тип товара: ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ (ПО)
[*]После оплаты покупатель получит: форму для заполнения регистрационных данных
[*]Торговая площадка: только в собственном магазине
[*]Мой магазин: указываете магазин из списка
[*]Теперь заполняете поля...
[list type=square]
[*]название программы
[*]trial version (free) - тут указываете ссылку на демо версию, где полный функционал активируется только после приобретения ключа
[*]цена
[*]описание программы
[/list]
[/list]
[*]Далее (в форме) указываете:
[box]
заполняемые поля:
[box]
[/box]
метод отправки: XML-запрос
URL для передачи XML-запроса: http://myserver.ru/product_register.php (это ваш php скрипт выше, который будет принимать xml запрос)
[/box]
[*]Указываете платёжные системы (те что регистрировали ранее).
[/list]
- Ваша программа -
[list type=upper-roman]
[*]Очень важно чтобы программа была востребована, но об этом читайте в статьях ниже.
[*]Чуть ниже описание и пример реализации вашей программы (что касается автоматизации регистрации).
[/list]
- Маркетинг -
[list type=upper-roman]
[*]Приложите усилия чтобы распространить ваш продукт и продвинуть его на разных площадках и программных платформах.
[/list]
- Время -
[list type=upper-roman]
[*]Ну, тут в принципе нечего сказать, постарайтесь найти его, причём в больших количествах!
[/list]
___________________________________
Программа на AutoIt
Реализация не сложная, ниже приведён пример программы (скрипт), который при запуске проверяет регистрационные данные.
[list type=upper-roman]
[*]При первом запуске (демо версия), скрипт предлагает зарегистрировать продукт, после удачной покупки покупатель получает ключ продукта который указывает в поле Product Key.
[*]Если покупатель со временем решит перенести свой продукт на другой компьютер, то в программе предусмотрено восстановление ключа продукта (если покупатель потерял свой файл ключей, то он может указать номер квитанции полученный при покупке в системе digiseller и получить новый ключ продукта - привязанный к новому компьютеру).
[*]Ключ продукта деактивируется в случае частых запросов восстановления, это может предотвратить совместное использование одной купленной лицензии.
[/list]
Вариант по проще...
Ссылки по материалу:
Как продать свою программу
предпродажная подготовка
Теория защиты программ от взлома
Как грамотно продавать интеллектуальные продукты?
Система защиты и привязка к железу
Привязка скрипта к одному компьютеру (железу) (теория в этой же теме)
_UniqueHardwaeIDv1() - Генерация уникального ID компьютера
- Данная статья не затрагивает вопрос о защите вашего ПО (имеется в виду де-компиляция и т.п.).
- В статье предполагается, что пользователь имеет базовые знания в php, xml, и веб-кодинге в целом, про AutoIt молчу .
- Методы реализации скриптов и обмена данными следует воспринимать как пример, их желательно изменить для использования на деле (проявите изобретательность и творчество). Потому как здесь они уже представлены на публичное обозрение, и это сильно ставит под вопрос надёжность, т.к зная алгоритм будет не сложно взломать, но это уже отдельная тема.
- Ссылки по материалам для данной статьи найдёте в конце.
С недавнего времени я всерьёз задумался над тем, что раньше для меня казалось немыслимо - продавать свои программы.
Но как оказалось, это довольно непростое и кропотливое занятие.
В конце этой статьи есть относительно простой вариант реализации данной задумки, но вариант представленный ниже, мне кажется более надёжным и интересным.
Что для этого нужно?
[list type=decimal]
[*]Свой сервер (хранение базы данных, исполнение php скриптов)
[*]Свой сайт (для размещения своих продуктов на продажу)
[*]Регистрация систем электронных денег (WebMoney, PayPal, Yandex.Money, и т.п.)
[*]Регистрация в платёжной системе (в данной статье рассматривается http://digiseller.ru - для упрощения процедуры продажи продукта)
[*]Хорошая программа с уникальным функционалом
[*]Энтузиазм и маркетинговые способности
[*]Свободное время (много)
[/list]
Теперь собственно разберём по частям, что требуется сделать:
- Сервер -
[list type=upper-roman]
[*]На сервере создаём базу данных, допустим назовём её MySoft.
[*]Далее на сервер нужно загрузить два php скрипта:
product_register.php - Отправка ответного xml запроса сервису
- Здесь меняем "digiseller_pass" на ваш пароль от системы digiseller, это нужно для проверки достоверности с запросом от системы (чтобы предотвратить ложный вызов скрипта).
- На этот скрипт будет отправляться запрос xml с сервиса digiseller, со всеми указанными параметрами (после оплаты продукта).
- Скрипт сам создаст таблицу (имя таблицы это id продукта в системе) в указанной базе со следующими полями:
db_cmd.php - Интеракция с базой данных (не рекомендуется делать это из AutoIt-скрипта, т.к в коде будут явно указаны данные доступа к базе данных
- В этот скрипт будут посылаться запросы с AutoIt-скрипта в виде команд, в соответствий с командой будут возвращаться данные или выполняться действия с базой данных.
- См. AutoIt-скрипт далее чтобы понять суть скрипта.
PHP:
<?php
$oXML = new SimpleXMLElement($GLOBALS['HTTP_RAW_POST_DATA']);
$sID = $oXML->id;
$sINV = $oXML->inv;
$sSIGN = $oXML->sign;
$sEMAIL = $oXML->email;
$sDATA = $oXML->data;
$xml = '<?xml version="1.0" encoding="windows-1251"?>
<response>
<id>' . $sID . '</id>
<inv>' . $sINV . '</inv>
';
$result = False;
//Check the signature (to recognize DigiSeller service)
if (md5($sID . ':' . $sINV . ':digiseller_pass') == $sSIGN) {
$sKey = GenerateProductKey($sDATA); //Generate key base on $sDATA (it's client hardware id passed by the DigiSeller system - entered by the client)
$xml .= ' <goods>
<![CDATA[
Your Product Key: <b>' . $sKey . '</b>
This key is unique for you only (hardware attached),
please keep the payment receipt (' . $sINV . ') to restore your key on other machine.
]]>
</goods>
';
//Connect to database (named as product id) and add row with registration data
$db_hostname = "myserver.ru";
$db_username = "username";
$db_password = "password";
$db_name = "db_name";
$db_table = $sID;
$hDB = mysql_connect($db_hostname, $db_username, $db_password); // or die("Unable to connect to MySQL");
$hSel = mysql_select_db($db_name, $hDB); // or die("Could not select examples");
$query = "CREATE TABLE IF NOT EXISTS `" . $db_table . "` (
`email` VARCHAR(100) NOT NULL,
`product_inv` INT(50) NOT NULL,
`hwid` VARCHAR(50) NOT NULL,
`activation_time` VARCHAR(500) NOT NULL,
`active` INT(1) NOT NULL DEFAULT '1')";
mysql_query($query);
$query = "INSERT INTO `" . $db_table . "` (
`email`,
`product_inv`,
`hwid`,
`activation_time`,
`active`) VALUES ('" . $sEMAIL . "', " . $sINV . ", '" . $sKey . "', '" . date("Y-m-d H:i:s") . "', 1);";
$result = mysql_query($query);
mysql_close($hDB);
}
if(!$result){
$xml .= '<error>
<![CDATA[
<b>Wrong Product ID or xml request!</b>
]]>
</error>';
}
$xml .= '</response>';
echo $xml;
function GenerateProductKey($sData)
{
$sRet_PK = '';
$aSplit_PK = str_split(preg_replace('~[^A-Z0-9]+~', '', strtoupper($sData)));
$iStep = 1;
$i = count($aSplit_PK);
foreach (array_reverse($aSplit_PK) as $sPart) {
if($iStep == 1)
{
$iStep = 0;
if(($i % 5) == 0)
{
$sRet_PK .= $sPart . '-';
} else {
$sRet_PK .= $sPart;
}
} else {
$iStep = 1;
}
$i -= 1;
}
return preg_replace('~\A-+|-+$|\A.{1,4}-|-.{1,4}$~', '', $sRet_PK);
}
?>
- На этот скрипт будет отправляться запрос xml с сервиса digiseller, со всеми указанными параметрами (после оплаты продукта).
- Скрипт сам создаст таблицу (имя таблицы это id продукта в системе) в указанной базе со следующими полями:
product_inv | hwid | activation_time | active | |
email покупателя | номер оплаченного счёта в системе учёта DIGISELLER | ключ продукта (привязка ПО к железу) | Дата активации | Состояние ключа продукта (активный или нет) |
db_cmd.php - Интеракция с базой данных (не рекомендуется делать это из AutoIt-скрипта, т.к в коде будут явно указаны данные доступа к базе данных
PHP:
<?php
$sFNC = $_GET['fnc'];
$sID = $_GET['id'];
$sINV = $_GET['inv'];
$sPK = strrev($_GET['pk']);
$sPK = substr($sPK, 4) . substr($sPK, 0, 4); //Assembl to real Product Key string
//Connect to database (named as product id) and add row with registration data
$db_hostname = "myserver.ru";
$db_username = "username";
$db_password = "password";
$db_name = "db_name";
$db_table = $sID;
$hDB = mysql_connect($db_hostname, $db_username, $db_password) or die("ERROR: Unable to connect to MySQL");
mysql_select_db($db_name, $hDB) or die("ERROR: Could not select examples");
$sRet = $sFNC($db_table, $sINV, $sPK);
echo $sRet;
mysql_close($hDB);
function get_inv($db_table, $sINV, $sPK)
{
$query = "SELECT product_inv FROM `" . $db_table . "` WHERE `hwid`='" . $sPK . "' AND `active`=1";
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
if (mysql_num_rows($result) == 0) return "ERROR: hwid not found or product_inv not active";
while ($row = mysql_fetch_assoc($result)) {
return $row['product_inv'];
}
}
function validate_inv($db_table, $sINV, $sPK)
{
$sTimes = '';
$query = 'SELECT * FROM `' . $db_table . '` WHERE `product_inv`=' . $sINV . ' AND `active`=1 LIMIT 1';
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
if (mysql_num_rows($result) == 0) return "ERROR: Invalid or inactive product_inv";
while ($row = mysql_fetch_assoc($result)) {
$sTimes = $row['activation_time'];
}
//Check if this product was licensed before
$aSplit_Times = explode('|', $sTimes);
//More than 10 times this soft was licensed
if (count($aSplit_Times) > 10) {
//If from first date to the last date passed less than 10 days, we deactivate this license (it's suspicious behaviour)
$datetime1 = new DateTime($aSplit_Times[1]);
$datetime2 = new DateTime($aSplit_Times[count($aSplit_Times)-1]);
$iDiff = $datetime1->diff($datetime2);
if ($iDiff->format('%a') < 10) {
deactivate_inv($db_table, $sINV, $sPK);
return "NO";
}
}
//We activate the inv - set new hwid, and add datetime to the activation_time column (to check later for hacking/multiple usage of product_inv)
return activate_inv($db_table, $sINV, $sPK);
}
function activate_inv($db_table, $sINV, $sPK)
{
$sTimes = '';
$query = 'SELECT * FROM `' . $db_table . '` WHERE `product_inv`=' . $sINV . ' AND `active`=1 LIMIT 1';
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
if (mysql_num_rows($result) == 0) return "ERROR: Invalid or inactive product_inv";
while ($row = mysql_fetch_assoc($result)) {
$sTimes = $row['activation_time'];
}
$sTimes .= ($sTimes !== '' ? '|' : '') . date("Y-m-d H:i:s");
$query = "UPDATE `" . $db_table . "` SET `hwid`='" . $sPK . "' WHERE `product_inv`=" . $sINV . " AND `active`=1";
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
//if (mysql_affected_rows() == 0) return "ERROR: Invalid or inactive product_inv";
$query = "UPDATE `" . $db_table . "` SET `activation_time`='" . $sTimes . "' WHERE `product_inv`=" . $sINV . " AND `active`=1";
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
if (mysql_affected_rows() == 0) return "ERROR: Invalid or inactive product_inv";
return "OK";
}
function deactivate_inv($db_table, $sINV, $sPK)
{
$query = "UPDATE `" . $db_table . "` SET `active`=0 WHERE `product_inv`=" . $sINV . " AND `active`=1";
$result = mysql_query($query);
if (!$result) return "ERROR: " . mysql_error();
if (mysql_affected_rows() == 0) return "ERROR: Invalid or inactive product_inv";
return "OK";
}
?>
- См. AutoIt-скрипт далее чтобы понять суть скрипта.
- Сайт -
[list type=upper-roman]
[*]Тут ничего сложного, создаёте свой сайт, где будет размещаться интернет магазин с вашими продуктами (такую возможность предоставляет сервис digiseller).
[/list]
- Системы электронных денег -
[list type=upper-roman]
[*]Регистрируете электронные деньги, такие как WebMoney, PayPal, Yandex.Money и другие. Стоит отметить, что при регистрации лучше сразу заполнять все данные и получать нужные сертификаты (см. справку для каждой платёжной системы отдельно), позже это упростит всю процедуру получения средств.
[/list]
- Платёжная система (digiseller) -
[list type=upper-roman]
[*]Регистрируетесь, создаёте свой магазин, получаете код для вставки на своём сайте (можно вставить на любой странице - это и будет страница вашего интернет магазина).
[*]Далее создаёте категорию своего ПО, и добавляете товар, где...
[list type=lower-alpha]
[*]Тип товара: ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ (ПО)
[*]После оплаты покупатель получит: форму для заполнения регистрационных данных
[*]Торговая площадка: только в собственном магазине
[*]Мой магазин: указываете магазин из списка
[*]Теперь заполняете поля...
[list type=square]
[*]название программы
[*]trial version (free) - тут указываете ссылку на демо версию, где полный функционал активируется только после приобретения ключа
[*]цена
[*]описание программы
[/list]
[/list]
[*]Далее (в форме) указываете:
[box]
заполняемые поля:
[box]
комментарий к полю: | имя поля: | заполнять: |
Data from your product (from demo version program) | data | Обязательно |
Email address | Обязательно |
метод отправки: XML-запрос
URL для передачи XML-запроса: http://myserver.ru/product_register.php (это ваш php скрипт выше, который будет принимать xml запрос)
[/box]
[*]Указываете платёжные системы (те что регистрировали ранее).
[/list]
- Ваша программа -
[list type=upper-roman]
[*]Очень важно чтобы программа была востребована, но об этом читайте в статьях ниже.
[*]Чуть ниже описание и пример реализации вашей программы (что касается автоматизации регистрации).
[/list]
- Маркетинг -
[list type=upper-roman]
[*]Приложите усилия чтобы распространить ваш продукт и продвинуть его на разных площадках и программных платформах.
[/list]
- Время -
[list type=upper-roman]
[*]Ну, тут в принципе нечего сказать, постарайтесь найти его, причём в больших количествах!
[/list]
___________________________________
Программа на AutoIt
Реализация не сложная, ниже приведён пример программы (скрипт), который при запуске проверяет регистрационные данные.
[list type=upper-roman]
[*]При первом запуске (демо версия), скрипт предлагает зарегистрировать продукт, после удачной покупки покупатель получает ключ продукта который указывает в поле Product Key.
[*]Если покупатель со временем решит перенести свой продукт на другой компьютер, то в программе предусмотрено восстановление ключа продукта (если покупатель потерял свой файл ключей, то он может указать номер квитанции полученный при покупке в системе digiseller и получить новый ключ продукта - привязанный к новому компьютеру).
[*]Ключ продукта деактивируется в случае частых запросов восстановления, это может предотвратить совместное использование одной купленной лицензии.
[/list]
Код:
#include <WinAPIDiag.au3>
#include <APIDiagConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <InetConstants.au3>
Global $sPRODUCT_NAME = 'My Program'
Global $sPRODUCT_ID = '12345' ;This is your product id from DigiSeller service
Global $sPRODUCT_URL = 'https://www.oplata.info/asp2/pay_pp.asp?id_d=' & $sPRODUCT_ID
Global $sDBCMD_URL = 'http://myserver.ru/db_cmd.php'
Global $sPRODUCT_INV = _ProductKey_Read('inv')
Global $sPRODUCT_HWID = _ProductKey_Read('hwid')
Global $fAPP_LICENSED = _ProductKey_Validate()
If $fAPP_LICENSED Then
MsgBox(64, 'Title', 'Full version code')
Exit
Else
_RegisterGUI()
EndIf
;.....
If $fAPP_LICENSED Then
MsgBox(64, 'Title', 'Full version code (after registration)')
EndIf
Func _RegisterGUI()
Local $hGUI, $iRegister_Bttn, $iData_Input, $iCopy_Bttn, $iPK_Input, $iRestorePK_Bttn, $iOk_Bttn, $iCancel_Bttn
Local $fHWID_Restored = False
$hGUI = GUICreate('Registration...', 500, 300)
GUICtrlCreateLabel('To use full version of this program, you must register', 20, 20)
GUICtrlCreateLabel('Copy DATA bellow and press "Register..." button', 20, 40)
$iRegister_Bttn = GUICtrlCreateButton('Register...', 20, 70, 80, 20)
GUICtrlCreateLabel('After successful payment you will be asked to set DATA field', 120, 72)
GUICtrlCreateLabel('DATA:', 20, 113)
$iData_Input = GUICtrlCreateInput(_ProductKey_GetHardwareData(), 60, 110, 340, 20, BitOR($GUI_SS_DEFAULT_INPUT, $ES_READONLY))
GUICtrlSetState(-1, $GUI_FOCUS)
$iCopy_Bttn = GUICtrlCreateButton('Copy', 420, 110, 60, 20)
GUICtrlCreateLabel('Product Key:', 20, 203)
$iPK_Input = GUICtrlCreateInput('', 100, 200, 380, 20)
$iRestorePK_Bttn = GUICtrlCreateButton('Restore product key...', 100, 220, 120, 20)
$iOk_Bttn = GUICtrlCreateButton('OK', 20, 270, 60, 20)
$iCancel_Bttn = GUICtrlCreateButton('Cancel', 100, 270, 60, 20)
GUISetState(@SW_SHOW, $hGUI)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE, $iCancel_Bttn
If $fHWID_Restored Then
Local $iAsk = MsgBox(52, 'Attention', _
'Are you sure? you already have restored the product key...' & @CRLF & @CRLF & _
'* If you cancel now, the restore point will be registered, many restore points in short time can cause license to be deactivated *', _
0, $hGUI)
If $iAsk <> 6 Then
ContinueLoop
EndIf
EndIf
$fAPP_LICENSED = False
_ProductKey_Delete('hwid')
_ProductKey_Delete('inv')
ExitLoop
Case $iRegister_Bttn
ShellExecute($sPRODUCT_URL)
Case $iCopy_Bttn
ClipPut(GUICtrlRead($iData_Input))
Case $iRestorePK_Bttn
If $fHWID_Restored Then
Local $iAsk = MsgBox(52, 'Attention', _
'Are you sure? you already have restored the product key...' & @CRLF & @CRLF & _
'* If you restore again, the restore point will be registered, many restore points in short time can cause license to be deactivated *', _
0, $hGUI)
If $iAsk <> 6 Then
ContinueLoop
EndIf
EndIf
$sInv = InputBox('Restore...', 'Please enter your payment receipt number (product_inv):', '', '', -1, -1, Default, Default, 0, $hGUI)
If $sInv <> '' Then
$sPRODUCT_INV = $sInv
$sPRODUCT_HWID = 'OLD_HWID'
$fAPP_LICENSED = _ProductKey_Validate()
If $fAPP_LICENSED Then
GUICtrlSetData($iPK_Input, $sPRODUCT_HWID)
$fHWID_Restored = True
Else
MsgBox(48, 'Error', 'Sorry, unable to restore your Product key, wrong payment receipt number (product_inv), or it''s blocked.', 0, $hGUI)
$fHWID_Restored = False
EndIf
EndIf
Case $iOk_Bttn
$sPRODUCT_HWID = GUICtrlRead($iPK_Input)
$fAPP_LICENSED = _ProductKey_Validate()
If $fAPP_LICENSED Then
_ProductKey_Write('hwid', $sPRODUCT_HWID)
_ProductKey_Write('inv', $sPRODUCT_INV)
MsgBox(64, 'Successful!', 'Now your product is licensed!', 0, $hGUI)
ExitLoop
EndIf
MsgBox(48, 'Error', 'Sorry, wrong Product Key', 0, $hGUI)
EndSwitch
WEnd
GUIDelete($hGUI)
EndFunc
Func _ProductKey_Validate()
Local $sPK = _ProductKey_GenerateKey()
;If hwid from registry match the current hardware id, then this soft is licensed
If $sPRODUCT_HWID == $sPK Then
;Set once the product_inv data
If $sPRODUCT_INV = '' Then
;Get product_inv data from our db_cmd.php wrapper
Local $sInv = _ProductKey_DBRequest('get_inv', $sPRODUCT_ID, $sPRODUCT_INV, $sPK)
;product_inv may be blocked
If @error Then
Return False
EndIf
_ProductKey_Write('inv', $sInv)
EndIf
Return True
EndIf
;If product_inv or product_hwid not found, then this soft is not licensed
If $sPRODUCT_INV = '' Or $sPRODUCT_HWID = '' Then
Return False
EndIf
Local $sValidate = _ProductKey_DBRequest('validate_inv', $sPRODUCT_ID, $sPRODUCT_INV, $sPK)
;@error will indicate that there was an error to connect to the database (you can use it to inform the user to contact the author)
If @error Then
Return SetError(1, 0, False)
EndIf
If $sValidate = 'OK' Then
$sPRODUCT_HWID = $sPK
_ProductKey_Write('hwid', $sPK)
Return True
Else
_ProductKey_Delete('hwid')
Return False
EndIf
EndFunc
Func _ProductKey_DBRequest($sFunc, $sID, $sINV, $sPK = '')
If $sPK <> '' Then
;Some sort of crypting method (decrypted later by db_cmd.php script)
$sPK = _ProductKey_Crypt($sPK)
EndIf
Local $sRet = InetRead($sDBCMD_URL & '?fnc=' & $sFunc & '&id=' & $sID & '&inv=' & $sINV & '&pk=' & $sPK, $INET_FORCERELOAD)
Local $iError = @error
$sRet = BinaryToString($sRet)
If $iError Or StringInStr($sRet, 'ERROR: ', 2) Then
Return SetError(1, 0, $sRet)
EndIf
Return $sRet
EndFunc
Func _ProductKey_GenerateKey($sHWID = '')
Local $sPK_Val = $sHWID
If $sHWID = '' Then
$sPK_Val = _ProductKey_GetHardwareData()
EndIf
Local $sRet_PK, $aSplit_PK = StringSplit(StringRegExpReplace(StringUpper($sPK_Val), "[^A-Z0-9]+", ""), "")
For $i = $aSplit_PK[0] To 1 Step -2
If Mod($i, 5) = 0 Then
$sRet_PK &= $aSplit_PK[$i] & "-"
Else
$sRet_PK &= $aSplit_PK[$i]
EndIf
Next
Return StringRegExpReplace($sRet_PK, "\A-+|-+$|\A.{1,4}-|-.{1,4}$", "")
EndFunc
Func _ProductKey_GetHardwareData()
Local $sUniqueHwID = _WinAPI_UniqueHardwareID(BitOR($UHID_MB, $UHID_BIOS))
$sUniqueHwID = StringTrimLeft($sUniqueHwID, 1)
$sUniqueHwID = StringTrimRight($sUniqueHwID, 1)
$sUniqueHwID &= '-AERTFG' & StringLeft($sPRODUCT_ID, 3) & '-FGGHFGME' & StringTrimLeft($sPRODUCT_ID, 3)
Return $sUniqueHwID
EndFunc
Func _ProductKey_Crypt($sPK)
Local $s_PK = ''
$s_PK &= StringRight($sPK, 4)
$s_PK &= StringLeft($sPK, 4)
$s_PK &= StringMid($sPK, 5, StringLen($sPK) - 8)
Return StringReverse($s_PK)
EndFunc
Func _ProductKey_Delete($sKey)
Local $iDel = IniDelete(@ScriptDir & '\Product.key', 'Data', $sKey)
If @error Or $iDel == 0 Then
RegDelete('HKLM\SOFTWARE\' & $sPRODUCT_NAME, $sKey)
EndIf
Return Number(@error = 0)
EndFunc
Func _ProductKey_Read($sKey)
Local $sRead = IniRead(@ScriptDir & '\Product.key', 'Data', $sKey, '@ERROR@')
If $sRead == '@ERROR@' Then
$sRead = RegRead('HKLM\SOFTWARE\' & $sPRODUCT_NAME, $sKey)
EndIf
Return $sRead
EndFunc
Func _ProductKey_Write($sKey, $sVal)
Local $iWrite = IniWrite(@ScriptDir & '\Product.key', 'Data', $sKey, $sVal)
If @error Or $iWrite == 0 Then
RegWrite('HKLM\SOFTWARE\' & $sPRODUCT_NAME, $sKey, 'REG_SZ', $sVal)
EndIf
Return Number(@error = 0)
EndFunc
Вариант по проще...
Создаёте на сервере php скрипт, который будет отправлять запрос на ваш email (где покупатель будет указывать квитанцию перевода средств от системы электронных денег и данные с вашего AutoIt-скрипта - данные о железе):
product_register.php
И используете следующий AutoIt скрипт в качестве примера:
MyProg.au3
* После получения данных на email, используем UNIQUE ID для генерации ключа продукта покупателя (используя _ProductKey_GenerateKey() из скрипта выше), и высылаем покупателю его ключ, который он введёт в соответствующее поле.
* Данный метод не предотвращает множественное использование оплаченного чека.
product_register.php
PHP:
<?php
$sApp = $_GET['app'];
$sImage = $_GET['img'];
$sLang = $_GET['lang'];
$sPrice = $_GET['price'];
$sPayment_Page = $_GET['ppage'];
$sEmail = $_GET['email'];
$sUNIQUEID = $_GET['uid'];
//Register (payment) form bellow
$sBody = 'Transfer #:%20%0D%0A%0D%0AEmail:%20%0D%0A%0D%0AUNIQUE ID: ' . $sUNIQUEID;
$sLng_Title = ($sLang == 'Russian' ? 'Покупка' : 'Buying');
$sLng_Price = ($sLang == 'Russian' ? 'Цена' : 'Price');
$sLng_Label1 = ($sLang == 'Russian' ? 'Пожалуйста, выполните соответствующую оплату на <a href="' . $sPayment_Page . '">странице покупки</a>, и <a href="mailto:' . $sEmail . '?subject=Product Key Request for ' . $sApp . '&body=' . $sBody . '">отправьте email</a> с номером/чеком перевода.' : 'Please make appropiate payment on the <a href="' . $sPayment_Page . '" target="_blank">payment page</a>, and <a href="mailto:' . $sEmail . '?subject=Product Key Request for ' . $sApp . '&body=' . $sBody . '">send email</a> with the transfer number/receipt.');
$sLng_Label2 = ($sLang == 'Russian' ? 'Пожалуйста, НЕ меняйте Тему и поле UNIQUE ID в теле письма' : 'Please do NOT change the subject and UNIQUE ID field in the body');
$sLng_Label3 = ($sLang == 'Russian' ? 'Просто добавьте номер перевода у поля "Transfer #:" или прикрепите к письму чек, а также укажите ваш email у поля "Email:"' : 'Just add transfer number to the "Transfer #:" field or attach receipt to the email, also enter your email to "Email:" field');
$sLng_Label4 = ($sLang == 'Russian' ? 'После подтверждения оплаты, Вы получите ключ продукта на указанный email' : 'When payment confirmed, you will recieve an email with your product key');
$sLng_Thanks = ($sLang == 'Russian' ? 'Спасибо что выбрали наш продукт :)' : 'Thank you for choosing our product :)');
echo '<body><title>' . $sLng_Title . ' ' .$sApp . '</title></body>';
echo '<h1>' . $sLng_Title . ' ' .$sApp . '</h1>
';
echo '<div style="text-align:center"><img src="' . $sImage . '" /></div>
';
echo '<b>' . $sLng_Price . ':</b> ' . $sPrice . '$
';
echo '<b>UNIQUE ID:</b> ' . $sUNIQUEID . '
';
echo $sLng_Label1 . '
';
echo '- <font style="color:red;font-weight:bold">' . $sLng_Label2 . '</font>
';
echo '- <font style="color:green;font-weight:bold">' . $sLng_Label3 . '</font>
';
echo '* <font style="color:gray;font-style:italic">' . $sLng_Label4 . '</font>
';
echo '<div style="text-align:center;font-weight:bold">' . $sLng_Thanks . '</div>
';
?>
И используете следующий AutoIt скрипт в качестве примера:
MyProg.au3
Код:
#include <WinAPIDiag.au3>
#include <APIDiagConstants.au3>
Global $sAPP_NAME = 'My Program'
Global $sAPP_PRICE = '10'
Global $sAPP_IMAGEURL = 'http://myserver.ru/images/MyApp.jpg'
Global $sAPP_EMAIL = '[email protected]'
Global $sPAYMENT_PAGE = 'http://myserver.ru/payment-page.html'
Global $sREGISTER_URL = 'http://myserver.ru/product_register.php'
Global $sPRODUCT_HWID = _ProductKey_Read('hwid')
Global $fAPP_LICENSED = _ProductKey_Validate()
If $fAPP_LICENSED Then
MsgBox(64, 'Title', 'Full version code')
Exit
Else
$sPage = StringFormat('?app=%s&img=%s&lang=%s&price=%s&ppage=%s&email=%s&uid=%s', _
$sAPP_NAME, $sAPP_IMAGEURL, 'English', $sAPP_PRICE, $sPAYMENT_PAGE, $sAPP_EMAIL, _ProductKey_GetHardwareData())
ShellExecute($sREGISTER_URL & $sPage)
$sPK = InputBox('Product key', 'Please enter your Product Key:', '')
If $sPK <> '' Then
$sPRODUCT_HWID = $sPK
$fAPP_LICENSED = _ProductKey_Validate()
EndIf
EndIf
;.....
If $fAPP_LICENSED Then
MsgBox(64, 'Title', 'Full version code (after registration)')
EndIf
Func _ProductKey_Validate()
Local $sPK = _ProductKey_GenerateKey()
If $sPRODUCT_HWID == $sPK Then
_ProductKey_Write('hwid', $sPK)
Return True
EndIf
Return False
EndFunc
Func _ProductKey_GenerateKey($sHWID = '')
Local $sPK_Val = $sHWID
If $sHWID = '' Then
$sPK_Val = _ProductKey_GetHardwareData()
EndIf
Local $sRet_PK, $aSplit_PK = StringSplit(StringRegExpReplace(StringUpper($sPK_Val), "[^A-Z0-9]+", ""), "")
For $i = $aSplit_PK[0] To 1 Step -2
If Mod($i, 5) = 0 Then
$sRet_PK &= $aSplit_PK[$i] & "-"
Else
$sRet_PK &= $aSplit_PK[$i]
EndIf
Next
Return StringRegExpReplace($sRet_PK, "\A-+|-+$|\A.{1,4}-|-.{1,4}$", "")
EndFunc
Func _ProductKey_GetHardwareData()
Local $sUniqueHwID = _WinAPI_UniqueHardwareID(BitOR($UHID_MB, $UHID_BIOS))
Local $sName = StringStripWS($sAPP_NAME, 8)
$sUniqueHwID = StringTrimLeft($sUniqueHwID, 1)
$sUniqueHwID = StringTrimRight($sUniqueHwID, 1)
$sUniqueHwID &= '-AERTFG' & StringLeft($sName, 3) & '-FGGHFGME' & StringTrimLeft($sName, 3)
Return $sUniqueHwID
EndFunc
Func _ProductKey_Read($sKey)
Local $sRead = IniRead(@ScriptDir & '\Product.key', 'Data', $sKey, '@ERROR@')
If $sRead == '@ERROR@' Then
$sRead = RegRead('HKLM\SOFTWARE\' & $sAPP_NAME, $sKey)
EndIf
Return $sRead
EndFunc
Func _ProductKey_Write($sKey, $sVal)
Local $iWrite = IniWrite(@ScriptDir & '\Product.key', 'Data', $sKey, $sVal)
If @error Or $iWrite == 0 Then
RegWrite('HKLM\SOFTWARE\' & $sAPP_NAME, $sKey, 'REG_SZ', $sVal)
EndIf
Return Number(@error = 0)
EndFunc
* После получения данных на email, используем UNIQUE ID для генерации ключа продукта покупателя (используя _ProductKey_GenerateKey() из скрипта выше), и высылаем покупателю его ключ, который он введёт в соответствующее поле.
* Данный метод не предотвращает множественное использование оплаченного чека.
Ссылки по материалу:
Как продать свою программу
предпродажная подготовка
Теория защиты программ от взлома
Как грамотно продавать интеллектуальные продукты?
Система защиты и привязка к железу
Привязка скрипта к одному компьютеру (железу) (теория в этой же теме)
_UniqueHardwaeIDv1() - Генерация уникального ID компьютера