bitrix24 rest api класс



как добавлять товары https://dev.1c-bitrix.ru/rest_help/crm/cases/add/how_to_product_binding.php
<?php
namespace nikaverro\dev\bitrix24;

use Bitrix\Main\Loader,
    Bitrix\Sale,
    Bitrix\Sale\Order,
    nikaverro\dev\catalog\service\orm\CatalogItemTable,
    nikaverro\dev\user\orm\UserTable,
    nikaverro\dev\dictionary\orm\CountryTable,
    nikaverro\user\User;

Loader::includeModule('nikaverro.dev');


class Bitrix24 {

    protected const URL = "https://nikaverro.bitrix24.ru/rest/[идентификатор_пользователя]/[код_вебхука]/";

    const CONTACT_TYPES = [
        "personal" => "CLIENT",
        "business" => "CLIENT",
        "edu" => "UC_OF4TS2",
        "dealer" => "UC_FZVJ48",
        "programmer" => "1"
    ];
    //доп свойства контакта
    const CONTACT_PROPS = [
        "dealerId" => "UF_CRM_1657012230", //id дилера
        "userId" => "UF_CRM_1656590023296", // id пользователя на nanocad.com
        "regConfirm" => "UF_CRM_1656590985288", //регистрация на nanocad.com подтверждена
        "countryText" => "UF_CRM_1657104920202", // страна текстом
        "country" => "UF_CRM_1657104083592" //страна списком
    ];

   const DEAL_TYPES = [
        "client" => "SALE", //прямая покупка клиентом
        "dealer" => "COMPLEX", //покупка через дилера
    ];
    const DEAL_STAGE = [
        "new" => "NEW",
        "success" => "WON",
        "lose" => "LOSE",
    ];
    //доп свойства сделки
    const DEAL_PROPS = [
        "orderId" => "UF_CRM_1656685544651", //номер заказа
        "dealerId" => "UF_CRM_1657011302", //id дилер
        "typeProduct" => "UF_CRM_1657277550279" //тип покупки (новая, продление, докупка
    ];

    const  DEAL_TYPE_PRODUCT = [
        "new" => 551,
        "prolong" => 557,
        "module" => 555,
        "workplace" => 553
    ];

    public static function SendRequest($method, $arData=[]){
        $queryUrl = self::URL.$method;
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $queryUrl,
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_POST => 1,
            CURLOPT_HEADER => 0,
            CURLOPT_RETURNTRANSFER => 1,
        ));
        if(!empty($arData)){
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($arData));
        }
        $result = curl_exec($curl);
        curl_close($curl);
        return json_decode($result,true);
    }

    static function CheckType($type=""){
        return (!empty($type) && in_array($type,["contact","lead","deal"])) ? true: false;
    }
    static function Add($type,$arFields){
        if(static::CheckType($type)) {
            $method = "crm." . $type . ".add";
            $arData = [
                "fields" => $arFields,
                "params" => [
                    "REGISTER_SONET_EVENT" => "N"
                ]
            ];
            $result = self::SendRequest($method, $arData);
        }
        return (!empty($result) && is_array($result) && !empty($result["result"])) ? $result["result"]: false;
    }

    static function Update($type,$id,$arFields){
        if(self::CheckType($type)) {
            $method = "crm." . $type . ".update";
            unset($arFields["ID"]); //на всякий случай
            $arData = [
                "id" => $id,
                "fields" => $arFields,
                "params" => [
                    "REGISTER_SONET_EVENT" => "N"
                ]
            ];
            $result = self::SendRequest($method, $arData);
        }
        return (!empty($result) && is_array($result) && !empty($result["result"])) ? $result["result"]: false;
    }


    public static function AddContact($arFields){ //добавляем в Б24 контакт
       return self :: Add("contact",$arFields);
    }
    public static function AddLead($arFields){ //добавляем в Б24 лид
        return self :: Add("lead",$arFields);
    }
    public static function AddDeal($arFields){  //добавляем в Б24 сделку
        return self :: Add("deal",$arFields);
    }
    public static function UpdateContact($contactId,$arFields){ //обновляем в Б24 контакт
        return self:: Update("contact", $contactId, $arFields);
    }
    public static function UpdateLead($leadId,$arFields){ //обновляем в Б24 лид
        return self:: Update("lead", $leadId, $arFields);
    }
    public static function UpdateDeal($dealId,$arFields){ //обновляем в Б24 сделку
        return self:: Update("deal", $dealId, $arFields);
    }
    public static function GetContactDataForAddByUser($user){
        $arResult = [];
        if(!empty($user)){
            if($user->isDealerAdmin()){
                $type = "dealer";
            }
            elseif ($user->isEdu()){
                $type = "edu";
            }
            else{
                $type = "personal";
            }
            $arResult = [
                "NAME" => $user->getName(),
                "LAST_NAME" => $user->getLastName(),
                self::CONTACT_PROPS["userId"] => $user->getId(),
                "TYPE_ID"=> self::CONTACT_TYPES[$type],
                "EMAIL" => [[
                    "VALUE"=>$user->getLogin(),
                    "VALUE_TYPE"=>"HOME",
                ]],
            ];

            if(!empty($user->getPersonalPhone())){
                $arResult["PHONE"] = [[
                    "VALUE"=>preg_replace("/[^0-9\.]/", '', $user->getPersonalPhone()),
                    "VALUE_TYPE"=>"HOME",
                ]];
            }
            if(!empty($user->getCountry())){
                $arResult[self::CONTACT_PROPS["country"]] = $user->getCountry()->getB24Id();
                $arResult[self::CONTACT_PROPS["countryText"]] = $user->getCountry()->getName();
            }
        }
        return $arResult;
    }
    public static function AddContactAfterRegister($arUser){ //добавляем в Б24 контакт после регистрации
        $arData = [
            "NAME" => $arUser['first_name'],
            "LAST_NAME" => $arUser['last_name'],
            "TYPE_ID"=> self::CONTACT_TYPES[$arUser["purpose"]]??"CLIENT",
            "EMAIL" => [[
                "VALUE"=>$arUser['email'],
                "VALUE_TYPE"=>"HOME",
            ]],
            self::CONTACT_PROPS["userId"] => $arUser["id"],
            //"COMMENTS" => $arUser['email']

        ];
        if(!empty($arUser["country"])){
            $arData[self::CONTACT_PROPS["country"]] = $arUser["country_b24id"]??"";
            $arData[self::CONTACT_PROPS["countryText"]] = $arUser["country_text"]??"";
        }

        if(!empty($arUser['phone'])){
            $arData["PHONE"] = [[
                "VALUE"=>preg_replace("/[^0-9\.]/", '', $arUser['phone']),
                "VALUE_TYPE"=>"HOME",
            ]];
            //$arData["COMMENTS"] .= " ".$arUser['phone'];

        }
//        $s = json_encode($arUser);
//        $arData["COMMENTS"] .= " ".$s;

        $contactId = static :: AddContact($arData);
        if($contactId){
           $user = UserTable::getByPrimary($arUser["id"])->fetchObject();
           $user->setB24Id($contactId);
           $user->save();
        }
        return $contactId;
    }

    public static function UpdateContactByUserId($userId,$arFields){ //обновляем в Б24 контакт
        $result = false;
        if($user = UserTable::getByPrimary($userId)->fetchObject()) {
            $contactId = $user->getB24Id();
            if (!empty($contactId)) {
                unset($arFields["ID"]); //на всякий случай
                $result = self::UpdateContact($contactId, $arFields);
            }
        }
        return $result;
    }

    public static function SetActiveContact($userId){ //ставим в Б24, что контакт активен (подтвердил регистрацию)
        return self :: UpdateContactByUserId($userId, [self::CONTACT_PROPS["regConfirm"]=>1]);
    }

    public static function AddDealByOrderId($orderId){
        $result = false;
        $dealId = false;
        \Bitrix\Main\Loader::includeModule("sale");
        $order = \Bitrix\Sale\Order::load($orderId);
        if(!empty($order)) {
            $batch = [];
            $arUserUpdate = [];
            $propertyCollection = $order->getPropertyCollection();
            $dealType = "";
            if($property = $propertyCollection->getItemByOrderPropertyCode("orderType")){
                if($property->getField('VALUE') == "dealer"){ //дилерский
                    $dealType = "dealer";
                    $dealer = UserTable::getByPrimary($order->getUserId())->fetchObject();
                    $contactDealerId = $dealer->getB24Id();
                    if(empty($contactDealerId)) {//дилера нет в Битрикс24, добавляем
                        $arData = self::GetContactDataForAddByUser($dealer);
                        $batch["dealer_add"] = 'crm.contact.add?'.http_build_query([
                            'fields'=>$arData,
                             'params' => [
                                 'REGISTER_SONET_EVENT' => 'N'
                             ]
                        ]);
                        $arUserUpdate["dealer_add"] = $dealer->getId();
                    }
                }
                else{ //клиентский
                    $dealType = "client";
                    $user = UserTable::getByPrimary($order->getUserId())->fetchObject();
                    $contactId = $user->getB24Id();
                    if(empty($contactId)) {//клиента нет в Битрикс24, добавляем
                        $arData = self::GetContactDataForAddByUser($user);
                        $batch["client_add"] = 'crm.contact.add?'.http_build_query([
                            'fields'=>$arData,
                            'params' => [
                                'REGISTER_SONET_EVENT' => 'N'
                            ]
                        ]);
                        $arUserUpdate["client_add"] = $user->getId();
                    }
                }
                //товары разбиваем на группы (по ключу installation)
                $basket = $order->getBasket();
                $basketItems = $basket->getBasketItems();
                $arItems = [];

                foreach ($basketItems as $basketItem){
                    $installation = $basketItem->getPropertyCollection()->getPropertyValues()["installation"]["VALUE"];
                    $summary = $basketItem->getPropertyCollection()->getPropertyValues()["summary"]["VALUE"];
                    $client = $basketItem->getPropertyCollection()->getPropertyValues()["client"]["NAME"];
                    $prolong = $basketItem->getPropertyCollection()->getPropertyValues()["prolong"]["NAME"];
                    $addModule = $basketItem->getPropertyCollection()->getPropertyValues()["module"]["NAME"];
                    $addWorkplace = $basketItem->getPropertyCollection()->getPropertyValues()["workplace"]["NAME"];

                    if (!empty($client)) {
                        $summary .= "<br /><br />" . $client;
                        $arItems[$installation]["client"] = str_replace('Customer: ','',$client);
                    }

                    $arItems[$installation]["totalBasePrice"] += ($basketItem->getBasePrice() * $basketItem->getField("QUANTITY"));
                    $arItems[$installation]["totalPrice"] += $basketItem->getPrice() * $basketItem->getField("QUANTITY");
                    $arItems[$installation]["installation"] = $installation;
                    $arItems[$installation]["summary"] = $summary;
                    $arItems[$installation]["hasDiscount"] = $basketItem->getPrice() != $basketItem->getBasePrice();
                    if(!empty($prolong)){
                        //$arItems[$installation]["prolong"] = $prolong;
                        $arItems[$installation]["type"] = "prolong";
                    }
                    if(!empty($addModule)){
                        $arItems[$installation]["type"] = "module";
                        //$arItems[$installation]["module"] = $addModule;
                    }
                    if(!empty($addWorkplace)){
                        $arItems[$installation]["type"] = "workplace";
                        //$arItems[$installation]["workplace"] = $addWorkplace;
                    }
                    $service = CatalogItemTable::loadType($basketItem->getField("PRODUCT_ID"));
                    if(!empty($service)) {
                        $serviceProps = $service->fill('PROPS');
                        $b24Id = $serviceProps->getB24Id();
                    }

                    $arItems[$installation]["items"][] = [
                        "id" => $basketItem->getID(),
                        "title" => $basketItem->getField("NAME"),
                        "price" => $basketItem->getPrice() * $basketItem->getField("QUANTITY"),
                        "discount" => $basketItem->getBasePrice() * $basketItem->getField("QUANTITY"),
                        "productID" => $basketItem->getField("PRODUCT_ID"),
                        "quantity" => intval($basketItem->getField("QUANTITY")),
                        "b24Id" => $b24Id ?? false
                    ];
                }
                $i = 0;
                foreach ($arItems as $installation => $arItem) { //каждую инсталляцию в отдельный заказ
                    $orderSum = 0;
                    if(empty($arItem["type"])){
                        $arItem["type"] = "new";
                    }
                    //собираем товары, считаем сумму сделки
                    $arDealProducts = [];
                    foreach ($arItem["items"] as $item) {
                        $orderSum = $orderSum + $item["price"]*$item["quantity"];
                        if(!empty($item["b24Id"])) {
                            $arDealProducts[] = [
                                "PRODUCT_ID" => $item["b24Id"],
                                "PRICE" => $item["price"].'.00',
                                "QUANTITY" => $item["quantity"]
                            ];
                        }
                    }

                    $arDeal = [
                        "TITLE" => "Заказ №".$orderId,
                        "TYPE_ID" => self::DEAL_TYPES[$dealType],
                        "CATEGORY_ID"=> 0,
                        "BEGINDATE"=> date("d.m.Y"),
                        "OPENED"=> "Y",
                        //
                        "CURRENCY_ID"=> "USD",
                        "OPPORTUNITY" => $orderSum,
                        "STAGE_ID"=> self::DEAL_STAGE["new"],
                        "ASSIGNED_BY_ID"=> 19, //Малышева
                        self::DEAL_PROPS["orderId"] => $orderId,
                        self::DEAL_PROPS["typeProduct"] => self::DEAL_TYPE_PRODUCT[$arItem["type"]]
                    ];
                    if($dealType == "dealer") {
                        $arDeal[self::DEAL_PROPS["dealerId"]] = !empty($contactDealerId) ? $contactDealerId : '$result[dealer_add]';

                        if(!empty($arItem["client"])) {

                            $userClient = UserTable::getBylogin($arItem["client"])->fetchObject();
                            if(!empty($userClient)) {
                                $contactId = $userClient->getB24Id();
                                if(empty($contactId)) {
                                    $arDataUser = self::GetContactDataForAddByUser($userClient);
                                    $batch["client_add_".$i] = 'crm.contact.add?'.http_build_query([
                                        'fields'=>$arDataUser,
                                        'params' => [
                                            'REGISTER_SONET_EVENT' => 'N'
                                        ]
                                    ]);
                                    $arUserUpdate["client_add_".$i] = $userClient->getId();
                                    $arDeal["CONTACT_ID"] = '$result[client_add_'.$i.']';
                                }
                                else {
                                    $arDeal["CONTACT_ID"] = $contactId;
                                }
                            }
                            else {
                                $arDeal["CONTACT_ID"]  = !empty($contactDealerId) ? $contactDealerId : '$result[dealer_add]';
                            }

                        }
                    }
                    else{ //client
                        $arDeal["CONTACT_ID"] = !empty($contactId) ? $contactId : '$result[client_add]';
                    }
                    //добавляем сделку
                    $batch["deal_add_".$i] = "crm.deal.add?".http_build_query([
                        'fields'=>$arDeal,
                        'params' => [
                            'REGISTER_SONET_EVENT' => 'N'
                        ]
                    ]);
                    //добавляем товары
                    if(!empty($arDealProducts)) {
                        $batch["row_set_".$i] = "crm.deal.productrows.set?".http_build_query([
                            'id'=> '$result[deal_add_'.$i.']',
                            'rows' => $arDealProducts
                        ]);
                    }

                    $i++;
                }
//                echo "<pre>";
//                print_r($batch);
//                echo "</pre>";
                $arData = [
                    "halt" => 1,
                    "cmd" => $batch
                ];
                $result = static::SendRequest("batch.json", $arData);

                $dealId = $result["result"]["result"]["deal_add_0"] ?? false;
                //echo $dealId;
                foreach ($arUserUpdate as $key =>$userId){
                    if(!empty($result["result"]["result"][$key])){
                        $user = UserTable::getByPrimary($userId)->fetchObject();
                        $user->setB24Id($result["result"]["result"][$key]);
                        $user->save();
                    }
                }
            }
        }
        return $dealId;
    }

    public static function UpdateDealByOrderId($orderId,$arFields){

        $arData = array(
            'filter' => array(
                self::DEAL_PROPS["orderId"] => $orderId,
            ),
            'select' => ['ID']
        );
        $result = self::SendRequest("crm.deal.list", $arData);
        if(!empty($result["result"])){
            sleep(2);
            $batch = [];
            foreach ($result["result"] as $item){
                if(!empty($item["ID"])){
                    $batch['upd_'.$item["ID"]] = 'crm.deal.update?'.http_build_query(array(
                            "id" => $item["ID"],
                            'fields' =>  $arFields
                        ));
                }
            }
            if(!empty($batch)) {
                $arData = [
                    "halt" => 1,
                    "cmd" => $batch
                ];
                $result = self::SendRequest("batch.json", $arData);
            }
        }
    }

    public static function SetDealPay($orderId){//переводим в успешный
        return self:: UpdateDealByOrderId($orderId,["STAGE_ID"=>self::DEAL_STAGE["success"]]);
    }
    public static function SetDealCancel($orderId){ //переводим в сделка провалена
        return self:: UpdateDealByOrderId($orderId,["STAGE_ID"=>self::DEAL_STAGE["lose"]]);
    }

    public static function AddProductsAll(){
        $items = CatalogItemTable::getList()->fetchCollection();
        $batch = [];
        foreach ($items as $item){
            $batch[$item->getId()] = 'crm.product.add?'.http_build_query([
                'fields'=>[
                    'NAME'=> $item->getTitle(),
                    'CURRENCY_ID'=> 'USD',
                    'PRICE' => intval($item->fillPrice()->getPrice()),
                    'SORT' => 500
                ]
            ]);
        }
        $arData = [
            "halt" => 0,
            "cmd" => $batch
        ];
        $result = self::SendRequest("batch.json", $arData);
        if(!empty($result["result"]["result"])){
            foreach ($result["result"]["result"] as $id => $bitrix24Id){
                if(!empty($bitrix24Id) && !empty($id)){
                    $service = CatalogItemTable::loadType($id);
                    $serviceProps = $service->fill('PROPS');
                    $serviceProps->setB24Id($bitrix24Id);
                    $service->save();
                }
            }
        }
    }
}