• Суд с фрилансером. Как быть в 2021?

    udjin123
    @udjin123
    PHP, Golang, React
    Самый реальный вариант, имхо это подать в суд на неосновательное обогащение если это реальный человек, а не дроп, на которого получил деньги мошенник. Если все таки нарвались на мошенника кто прогнал деньги через подставное лицо то сходить написать заявление в полицию, и именно добиться чтобы зарегистрировали его, хотя будут уговаривать этого не делать (совсем работать не хотят)
    Ответ написан
    1 комментарий
  • Как в письмо с данными о заказе отправляемое покупателю добавить текстовый файл с данными о заказе?

    udjin123
    @udjin123
    PHP, Golang, React
    Почтовые события позволяют прикреплять файлы в письмо, но вмешаться в событие SALE_NEW_ORDER отправки письма о новом заказе вы не можете. Как вариант деактивировать штатное почтовое событие SALE_NEW_ORDER, создать свое и вызывать его прикрепляя файл подписавшись на событие в php_interface на создание заказа, событие из d7 - OnSaleOrderSaved проверять флаг IS_NEW. Документация по нему тут
    Ответ написан
    1 комментарий
  • Есть ли возможность сделать скрипт в Битрикс24?

    udjin123
    @udjin123
    PHP, Golang, React
    1. Стоит уточнить облако или коробка.
    2. Реализовать можно бизнес-процессом
    Ответ написан
    2 комментария
  • Как из пользовательских списков, которые привязаны к элементу CRM Компания вытащить информацию в создании сделки только для данной компании?

    udjin123
    @udjin123
    PHP, Golang, React
    1. Стоит уточнить облако или коробка
    2. Решается легко бизнес процессом
    3. Доп поле с типом привязка элементам инфоблоков, в название серийный номер, список оборудования будет весь, иначе пробовать через создание своего пользовательского типа.
    Ответ написан
  • Чем может быть чревато удаление нулевых остатков?

    udjin123
    @udjin123
    PHP, Golang, React
    Это справочная информация, в логике ядра не задействована, смело можно тереть.
    Даже при добавлении нового склада для всех товаров автоматом записи по складам не создаются. Что очень хорошо видно, пустые поля без 0 в админке
    Ответ написан
    Комментировать
  • Как посмотреть массив данных о товаре, передаваемых при импорте из 1С?

    udjin123
    @udjin123
    PHP, Golang, React
    1. Это далеко не первый вопрос, все дело в неправильном подходе, вот тут например отвечал уже.
    2. Событие OnBeforeIBlockElementUpdate для этого не подходит, для остатков складов используйте событие OnStoreProductUpdate и OnStoreProductAdd. Все события изменения/добавления цен, основного остатка, остатков складов и т.д. лежат в модуле Торговый каталог, список смотреть тут
    Ответ написан
    Комментировать
  • Как проверить строку, есть ли в начале определенные символы?

    udjin123
    @udjin123
    PHP, Golang, React
    strings.HasPrefix("Gopher", "Go")

    Документация тут
    Ответ написан
    Комментировать
  • Как сделать перенаправление с www в Bitrix virtual appliance version 7.4.4?

    udjin123
    @udjin123
    PHP, Golang, React
    Чуть дополню ответ выше.

    Редиректы в BitrixEnv можно сделать на нескольких уровнях:
    1. На уровне nginx (редко используется если дальше apache)
    2. На уровне apache (в htaccess)
    3. На уровне PHP (свой код или готовый модуль)

    Вот о последнем как раз чуть подробнее, для людей без специальных знаний это самый идеальный вариант. Достаточно установить готовый бесплатный модуль из маркетплейса битрикса для управления редиректами, и настройка всех редиректов сведется к паре кликов.
    Ответ написан
    Комментировать
  • Как подключить библиотеки из JSON?

    udjin123
    @udjin123
    PHP, Golang, React
    Можно, но этого не достаточно, нужны будут еще дополнительные манипуляции. И как раз чтобы не делать это все руками, есть инструменты которые это делают все автоматически.
    По этому лучше установить nodejs, потом менеджер пакетов npm или yarn и "собрать" то что вы хотите (как это делать инструкций полно в инете), в результате на выходе будет один файл javascipt который и уже спокойно воткнете на свой сайт.
    Ответ написан
    2 комментария
  • Как сделать на сайте письмо со счетом на оплату в pdf?

    udjin123
    @udjin123
    PHP, Golang, React
    В битриксе в модуле Sale есть класс CSalePdf для работы с PDF, его используют системные платежные службы.
    Пример использования и реализации смотреть в исходниках службы "Счет (bill)"
    Исходник лежит тут bitrix\modules\sale\handlers\paysystem\bill\template\template_pdf.php
    Ответ написан
    Комментировать
  • Что делать при удалении через rm всех файлов из корневой папки?

    udjin123
    @udjin123
    PHP, Golang, React
    Все тоже самое что и на всех операционках и дисках многие года.
    Извлекаем диск подключаем к другому компу и любой утилитой восстановления удаленных файлов вытаскиваем важные данные. Систему лучше переустановить, так как вновь удаленные файлы будут вперемешку с удаленными ранее, которых может быть оооочень много и это очень титанический труд будет привести все в рабочий вид. Короче легче вытащить данные и все снести и поставить заново.

    ЗЫ Советую поменьше включать комп и пытаться грузить, так как удаленные файлы, на самом деле не удалены, а всего лишь помечены как свободное место и их блоки будут постепенно перезаписываться.
    Ответ написан
  • Как узнать, что находится в полях $orderFields обработчика OnOrderSave?

    udjin123
    @udjin123
    PHP, Golang, React
    Начать использовать xdebug, вместо var_dump, print_r и прочих костылей, аля запись дампов в лог, которые еще и забывают убрать из прода.
    Ответ написан
    Комментировать
  • КАК получить документ в Битрикс24?

    udjin123
    @udjin123
    PHP, Golang, React
    Это обычный элемент инфоблока, получить можно с помощью метода

    lists.element.get(params)

    Вот тут его описание тык
    Ответ написан
    2 комментария
  • Как вынуть публичный ключ из сертификата, для дальнейшей подписи и шифрования данных через библиотеку CryptoAPI?

    udjin123
    @udjin123
    PHP, Golang, React
    В КриптоПро SDK есть хорошие примеры работы с подписями на C++. Мне когда то очень помогли, когда в Golang делал работу с ЭЦП. Пришлось вставки на Си делать. Посоветую скачать и изучить.

    Вот пример от туда - открывается хранилище, получается сертификат, далее получает ссылку на закрытый ключ ну и создание и подписание хеша

    #pragma warning(disable : 4996)
    
    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <wchar.h>
    
    #ifdef _WIN32
    #include <tchar.h>
    #else
    #include <cstdio>
    #include "reader/tchar.h"
    #endif
    
    #include "cades.h"
    
    /*
    Пример создания усовершенствованной подписи CADES_X_LONG_TYPE_1 с помощью
    упрощённых функций КриптоПро ЭЦП SDK по хэш-значению. Пример подписывает
    произвольные данные, которые формирует самостоятельно. Результат будет сохранен
    в файл sign.dat. Для подписи необходимо чтобы в хранилище сертификатов
    присутствовал сертификат с закрытым ключом и ссылкой на работающую OCSP службу
    */
    
    using namespace std;
    
    #include "../samples_util.h"
    
    int main(int argc, char *argv[]) {
        // Открываем хранилище сертификатов пользователя
        HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));
    
        if (!hStoreHandle) {
            cout << "Store handle was not got" << endl;
            return -1;
        }
    
        wchar_t *wa = NULL;
        if (argc > 1) {
            size_t len = strlen(argv[1]) + 1;
            wa = new wchar_t[len];
            mbstowcs(wa, argv[1], len);
        }
    
        // Получаем сертификат для подписания
        PCCERT_CONTEXT context = GetRecipientCert(hStoreHandle, wa);
        if (wa) delete[] wa;
    
        // Если сертификат не найден, завершаем работу
        if (!context) {
            cout << "There is no certificate with a CERT_KEY_CONTEXT_PROP_ID "
                 << endl << "property and an AT_KEYEXCHANGE private key available."
                 << endl
                 << "While the message could be sign, in this case, it could"
                 << endl << "not be verify in this program." << endl
                 << "For more information, read the documentation "
                    "http://cpdn.cryptopro.ru/" << endl;
            return -1;
        }
    
        HCRYPTPROV hProv(0);
    
        DWORD dwProvType = PROV_GOST_2012_256;
    
        // Получаем ссылку на закрытый ключ сертификата и дестриптор
        // криптопровайдера
        if (!CryptAcquireContext(&hProv, 0, NULL, dwProvType,
                                 CRYPT_VERIFYCONTEXT)) {
            CertFreeCertificateContext(context);
            cout << "CryptAcquireContext() failed" << endl;
            return -1;
        }
    
        // Задаем параметры
        CRYPT_SIGN_MESSAGE_PARA signPara = {sizeof(signPara)};
        signPara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
        signPara.pSigningCert = context;
        signPara.HashAlgorithm.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_256;
    
        CADES_SIGN_PARA cadesSignPara = {sizeof(cadesSignPara)};
        cadesSignPara.dwCadesType = CADES_BES;
    
        CADES_SIGN_MESSAGE_PARA para = {sizeof(para)};
        para.pSignMessagePara = &signPara;
        para.pCadesSignPara = &cadesSignPara;
    
        // Формируем данные для подписания
        vector<unsigned char> data(10, 25);
    
        CERT_CHAIN_PARA		ChainPara = { sizeof(ChainPara) };
        PCCERT_CHAIN_CONTEXT	pChainContext = NULL;
    
        std::vector<PCCERT_CONTEXT> certs;
    
        if (CertGetCertificateChain(
            NULL,
            context,
            NULL,
            NULL,
            &ChainPara,
            0,
            NULL,
            &pChainContext)) {
    
            for (DWORD i = 0; i < pChainContext->rgpChain[0]->cElement - 1; ++i)
            {
                certs.push_back(pChainContext->rgpChain[0]->rgpElement[i]->pCertContext);
            }
        }
        // Добавляем в сообщение цепочку сертификатов без корневого
        if (certs.size() > 0)
        {
            signPara.cMsgCert = (DWORD)certs.size();
            signPara.rgpMsgCert = &certs[0];
        }
    
        // Получение хэша данных
        HCRYPTHASH hash(0);
        if (!CryptCreateHash(hProv, CALG_GR3411_2012_256, 0, 0, &hash)) {
            CryptReleaseContext(hProv, 0);
            CertFreeCertificateContext(context);
            cout << "CryptCreateHash() failed" << endl;
            return -1;
        }
    
        DWORD cbToBeSigned(0);
        DWORD cb = sizeof(cbToBeSigned);
        BYTE *pbToBeSigned;
    
        switch (CryptHashData(hash, &data[0], (DWORD) data.size(), 0)) {
            case TRUE:
                if (!CryptGetHashParam(hash, HP_HASHSIZE, (LPBYTE) &cbToBeSigned, &cb,
                                       0)) {
                    CryptReleaseContext(hProv, 0);
                    CertFreeCertificateContext(context);
                    CryptDestroyHash(hash);
                    cout << "CryptGetHashParam() failed" << endl;
                    return -1;
                }
    
                pbToBeSigned = new BYTE[cbToBeSigned];
    
                if (!CryptGetHashParam(hash, HP_HASHVAL, pbToBeSigned, &cbToBeSigned,
                                       0)) {
                    delete[] pbToBeSigned;
                    CryptReleaseContext(hProv, 0);
                    CertFreeCertificateContext(context);
                    CryptDestroyHash(hash);
                    cout << "CryptGetHashParam() failed" << endl;
                    return -1;
                }
                break;
            default:
                CryptReleaseContext(hProv, 0);
                CertFreeCertificateContext(context);
                CryptDestroyHash(hash);
                cout << "CryptHashData() failed" << endl;
                return -1;
        }
    
        PCRYPT_DATA_BLOB pSignedMessage = 0;
    
        string contentType(szOID_RSA_data);
    
        // Создаем подписанное сообщение
        if (!CadesSignHash(&para, pbToBeSigned, cbToBeSigned, contentType.c_str(), &pSignedMessage)) {
            delete[] pbToBeSigned;
            CryptReleaseContext(hProv, 0);
            CertFreeCertificateContext(context);
            CryptDestroyHash(hash);
            cout << "CadesSignHash() failed" << endl;
            return -1;
        }
    
         delete[] pbToBeSigned;
    
        vector<unsigned char> message(pSignedMessage->cbData);
        copy(pSignedMessage->pbData,
             pSignedMessage->pbData + pSignedMessage->cbData, message.begin());
    
        // Сохраняем результат в файл sign.dat
        if (SaveVectorToFile<unsigned char>("sign.dat", message)) {
            CryptReleaseContext(hProv, 0);
            CertFreeCertificateContext(context);
            CryptDestroyHash(hash);
            cout << "CryptHashData() failed" << endl;
            cout << "Signature was not saved" << endl;
            return -1;
        }
    
        cout << "Signature was saved successfully" << endl;
    
        // Освобождаем структуру с закодированным подписанным сообщением
        if (!CadesFreeBlob(pSignedMessage)) {
            CryptReleaseContext(hProv, 0);
            CertFreeCertificateContext(context);
            CryptDestroyHash(hash);
            cout << "CadesFreeBlob() failed" << endl;
            return -1;
        }
    
        // Закрываем хранилище
        if (!CertCloseStore(hStoreHandle, 0)) {
            CryptReleaseContext(hProv, 0);
            CertFreeCertificateContext(context);
            CryptDestroyHash(hash);
            cout << "Certificate store handle was not closed." << endl;
            return -1;
        }
    
        // Освобождаем ресурсы
        CryptReleaseContext(hProv, 0);
        CertFreeCertificateContext(context);
        CryptDestroyHash(hash);
    
        return 0;
    }
    Ответ написан
    2 комментария
  • Как можно сделать корзину и оформление заказа в сплывающей форме ,чтобы не уходить со страницы?

    udjin123
    @udjin123
    PHP, Golang, React
    В редакции Старт нет интернет магазина, есть сторонние платные решения на маркетплейс которые превращают его в магазин. (Пример)

    Ну или все самому с нуля вооружившись документацией битрикс, и используя php и javascript.
    Ответ написан
  • Куда добавлять свои классы в Bitrix?

    udjin123
    @udjin123
    PHP, Golang, React
    Есть несколько способов, главное помнить что классы не ради классов, а для поддерживаемого кода и его повторного использования.

    1. Автозагрузка классов с помощью Composer (многие используют).
    2. Написать свою автозагрузку. (если у вас что то сильно не стандартное)
    3. В виде модуля bitrix, автозагрузка будет (имхо самый правильный вариант для битрикса)

    При использовании composer, файлы классов могут лежать, где угодно, но хорошей практикой считается хранить их (как и папку vendor) на уровень выше публичной папки.
    В Namespace вы не ограничены, главное делайте явную и четкую структуру и названия несущие смысловую нагрузку.

    ЗЫ: Не забываем про DRY, KISS, SOLID и т.д.
    Ответ написан
    Комментировать
  • Правильный подход к разработке на Bitrix?

    udjin123
    @udjin123
    PHP, Golang, React
    Vscode лучше заменить на PhpStorm.
    На локалке все прекрасно разворачивается, в том числе на openserver, только вот окружение надо создавать максимально близкое к боевому. По этому имхо под виндой лучший вариант docker в wsl2. Для докера готовое решение смотрите bitrixdoc.
    Ответ написан
    Комментировать
  • Как ограничить кол-во товара в одни руки Bitrix?

    udjin123
    @udjin123
    PHP, Golang, React
    Используйте события OnBeforeBasketAdd и OnBeforeBasketUpdate
    В обработчике проверяйте условие и корректируйте количество в корзине.
    Ответ написан
    Комментировать