First encryption

So we should encrypt our request

Keys that you should use for encryption: https://nanokassa.ru/integration/documentation/publichnye-rsa-klyuchi/

So lets encrypt this request:

{
    "kassaid": "123456",
    "kassatoken": "12345678912345678912345678912345",
    "cms": "ss7-7.3.0.209",
    "check_send_type": "email",
    "products_arr": [{
        "name_tovar": "\u041a\u0430\u0440\u0442\u043e\u043d\u043d\u0430\u044f \u043a\u043e\u0440\u043e\u0431\u043a\u0430 2, 11112",
        "price_piece_bez_skidki": 7744,
        "skidka": 1297,
        "kolvo": 2,
        "price_piece": 7095,
        "summa": 14191,
        "stavka_nds": 6,
        "priznak_sposoba_rascheta": 4,
        "priznak_predmeta_rascheta": 1,
        "priznak_agenta": "none",
        "phone_oper_perevoda": "",
        "operation_plat_agenta": "",
        "phone_oper_priem_plat": "",
        "name_oper_perevoda": "",
        "address_oper_perevoda": "",
        "inn_oper_perevoda": "",
        "phone_postavshika": "",
        "name_postavshika": "",
        "discount": {
            "type": "amount",
            "value": 12.97
        }
    }, {
        "name_tovar": "\u0423\u043f\u0430\u043a\u043e\u0432\u043a\u0430",
        "price_piece_bez_skidki": 155,
        "skidka": 26,
        "kolvo": 2,
        "price_piece": 142,
        "summa": 284,
        "stavka_nds": 6,
        "priznak_sposoba_rascheta": 4,
        "priznak_predmeta_rascheta": 4,
        "priznak_agenta": "none",
        "phone_oper_perevoda": "",
        "operation_plat_agenta": "",
        "phone_oper_priem_plat": "",
        "name_oper_perevoda": "",
        "address_oper_perevoda": "",
        "inn_oper_perevoda": "",
        "phone_postavshika": "",
        "name_postavshika": "",
        "discount": {
            "type": "amount",
            "value": 0.26
        }
    }, {
        "name_tovar": "\u041a\u0430\u0440\u0442\u043e\u043d\u043d\u0430\u044f \u043a\u043e\u0440\u043e\u0431\u043a\u0430 2, 11112",
        "price_piece_bez_skidki": 2277,
        "skidka": 191,
        "kolvo": 1,
        "price_piece": 2086,
        "summa": 2086,
        "stavka_nds": 6,
        "priznak_sposoba_rascheta": 4,
        "priznak_predmeta_rascheta": 1,
        "priznak_agenta": "none",
        "phone_oper_perevoda": "",
        "operation_plat_agenta": "",
        "phone_oper_priem_plat": "",
        "name_oper_perevoda": "",
        "address_oper_perevoda": "",
        "inn_oper_perevoda": "",
        "phone_postavshika": "",
        "name_postavshika": "",
        "discount": {
            "type": "amount",
            "value": 1.91
        }
    }, {
        "name_tovar": "\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430: PickPoint",
        "price_piece": 30000,
        "summa": 30000,
        "kolvo": 1,
        "stavka_nds": 6,
        "priznak_sposoba_rascheta": 4,
        "priznak_predmeta_rascheta": 1,
        "priznak_agenta": "none",
        "phone_oper_perevoda": "",
        "operation_plat_agenta": "",
        "phone_oper_priem_plat": "",
        "name_oper_perevoda": "",
        "address_oper_perevoda": "",
        "inn_oper_perevoda": "",
        "phone_postavshika": "",
        "name_postavshika": "",
        "deliveryposition": "yes"
    }],
    "oplata_arr": {
        "rezhim_nalog": "2",
        "money_nal": 0,
        "money_electro": 46561,
        "money_predoplata": 0,
        "money_postoplata": 0,
        "money_vstrecha": 0,
        "kassir_inn": "",
        "kassir_fio": "",
        "client_email": "support@nanokassa.ru",
        "client_phone": "123"
    },
    "itog_arr": {
        "priznak_rascheta": 1,
        "itog_cheka": 46561
    }

This big request will become this small encrypted request:

{
    "ab":"GYBhagdYGWgahjGDHASgdjhas...ASDGd", 
    "de":"GYBhagdYGWgahjGDHASgdjhas...ASDGd", 
    "kassaid":"123456", 
    "kassatoken":"3212312312312", 
    "test":"1"
}

So lets see on that parameters.

Parameters kassaid and kassatoken - for authentication.

In parameter test you should specify if this request is test or army. Attention! You must fill it! If you will not fill it - so it will be army request and this request will go to cashbox. (Available values: 0; 1) (1 - test request. 0 - army request). This parameter you should fill in both encryptions. Dont forget about this. After this you should encrypt this request.

In parameter ab there is a key for decrypt parameter de. Parameter ab encrypted with RSA

In parameter de there is a main packet with data. Parameter de encrypted with AES256-CTR. Every key is different. Key you will know only if you will decrypt packet ab (RSA)

These functions (on PHP) (dont forget to install openssl extension), work correctly with encrypting (request is just for example). For using AES256-CTR you should use openssl_encrypt.

$request = '{
"kassaid": "123456", "kassatoken": "3212312312312", "cms":"xxx", ... "card_amount": 3934
}';
$IVdata = random_bytes(16);
$pw = random_bytes(32);
$mk = 'xxx'; // hmac control in base64
$dataAES = openssl_encrypt($request, "aes-256-ctr", $pw, OPENSSL_RAW_DATA, $IVdata);
$hmac = hash_hmac('sha512', $IVdata.$dataAES, base64_decode($mk), true);
$returnDataDE = base64_encode($hmac.$IVdata.$dataAES);

So structure of parameter de should have: 64 bytes of HMAC, 16 bytes of IVDATA, and other bytes - main packet.

Lets see on parameter ab. 

These functions (on PHP) (dont forget to install openssl extension), work correctly with encrypting (pubkey is just for example). For using RSA you should use openssl_public_encrypt function.

$pubkey = "-----BEGIN PUBLIC KEY-----
HASGDHJASGDASDSAGD .... 
SADGHASDHASJGDAHJS==
-----END PUBLIC KEY-----";
openssl_public_encrypt($pw, $ab_rsa, $pubkey, OPENSSL_PKCS1_OAEP_PADDING)
$ab = base64_encode ($ab_rsa);
$returnDataAB = $ab;

Теперь мы можем уже понять, как получить вот такой пакет. 

{    
    "ab":"GYBhagdYGWgahjGDHASgdjhas...ASDGd",     
    "de":"GYBhagdYGWgahjGDHASgdjhas...ASDGd",     
    "kassaid":"123456",     
    "kassatoken":"3212312312312",     
    "test":"1"
}

Going to second encryption.