<?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();
}
}
}
}
} |