GithubHelp home page GithubHelp logo

ufee / amoapi Goto Github PK

View Code? Open in Web Editor NEW
42.0 8.0 18.0 368 KB

AmoCRM PHP API/oAuth Client

Home Page: https://www.amocrm.ru/developers/content/platform/abilities

License: MIT License

PHP 100.00%
amocrm php api crm oauth

amoapi's Introduction

AmoCRM API Client

Api клиент для работы с amoCRM
Поддержка oAuth авторизации начиная с версии 0.9.0.0

Установка

composer require ufee/amoapi

Запуск тестов

Отредактировать vendor/ufee/amoapi/tests/Config.php

composer require --dev phpunit/phpunit ^5
vendor/bin/phpunit vendor/ufee/amoapi

Инициализация клиента по oAuth

Хранение oauth токена возможно в нескольких вариантах

Файловое хранилище

Используется по умолчанию (/vendor/ufee/amoapi/src/Cache/), можно задать свой путь
Создается поддиректория: {path}/{domain}/{client_id}.json
Настоятельно рекомендуется использовать cвой путь для кеширования, в противном случае данные будут УДАЛЕНЫ composer'ом при обновлении на новую версию.

\Ufee\Amo\Oauthapi::setOauthStorage(
	new \Ufee\Amo\Base\Storage\Oauth\FileStorage(['path' => '/full/oauth/path'])
);

Redis

Поддерживается библиотека phpredis
Формат ключа: {domain}_{client_id}

$redis = new \Redis();
$redis->connect('/var/run/redis/redis.sock');
$redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
$redis->select(5); // switch to specific db

\Ufee\Amo\Oauthapi::setOauthStorage(
	new \Ufee\Amo\Base\Storage\Oauth\RedisStorage(['connection' => $redis])
);

MongoDB

Поддерживается библиотека mongodb

$mongo = new \MongoDB\Client('mongodb://host');
$collection = $mongo->selectCollection('database', 'some_collection');

\Ufee\Amo\Oauthapi::setOauthStorage(
	new \Ufee\Amo\Base\Storage\Oauth\MongoDbStorage(['collection' => $collection])
);

Наследование хранилища

Реализуется класс, наследующий \Ufee\Amo\Base\Storage\Oauth\AbstractStorage

class CustomOauthStorage extends \Ufee\Amo\Base\Storage\Oauth\AbstractStorage
{
	protected function initClient(Oauthapi $client) {
		parent::initClient($client);
		$key = $client->getAuth('domain').'_'.$client->getAuth('client_id');
		if ($data = getClientOauthData($key)) {
			static::$_oauth[$key] = $data;
		}
	}
	public function setOauthData(Oauthapi $client, array $oauth) {
		parent::setOauthData($client, $oauth);
		$key = $client->getAuth('domain').'_'.$client->getAuth('client_id');
		return setClientOauthData($key, $oauth);
	}
}
\Ufee\Amo\Oauthapi::setOauthStorage(
	new CustomOauthStorage()
);

Стороннее хранение

Кеширование oauth данных библиотекой не производится

\Ufee\Amo\Oauthapi::setOauthStorage(
	new \Ufee\Amo\Base\Storage\Oauth\AbstractStorage()
);
$amo = \Ufee\Amo\Oauthapi::setInstance([...]);
$first_token = $amo->fetchAccessToken($code);
saveToCustomStorage($first_token);
$last_saved_token = getFromCustomStorage();
$amo->setOauth($last_saved_token);
$amo->onAccessTokenRefresh(function($oauth) {
	saveToCustomStorage($oauth);
});

Deprecated

Задать свой путь для кеширования oauth данных (устаревший метод)

$amo->setOauthPath('path_to/oauth');
// equal to new method
\Ufee\Amo\Oauthapi::setOauthStorage(
    new \Ufee\Amo\Base\Storage\Oauth\FileStorage(['path' => 'path_to/oauth'])
);

Получение объекта для работы с конкретным аккаунтом

$amo = \Ufee\Amo\Oauthapi::setInstance([
    'domain' => 'testdomain',
    'client_id' => 'b6cf0658-b19...', // id приложения
    'client_secret' => 'D546t4yRlOprfZ...',
    'redirect_uri' => 'https://site.ru/amocrm/oauth/redirect',
    'zone' => 'ru', // or com
    'timezone' => 'Europe/Moscow',
    'lang' => 'ru', // or en
    'user_agent' => '' // ifempty = Amoapi v.<version> (<client_id>)
]);
$amo->setAuth('user_agent', 'MyCustomUserAgent');

Получение ранее инициализированного объекта по id приложения

$amo = \Ufee\Amo\Oauthapi::getInstance('b6cf0658-b19...');

Получение URL авторизации в приложении amoCRM
Необходимо для извлечения кода авторизации

$first_auth_url = $amo->getOauthUrl($arg = ['mode' => 'popup', 'state' => 'amoapi']);

Получение oauth данных - access_token, refresh_token производится единоразово, по коду авторизации
Полученные данные oauth кешируются в соответствии с выбранным хранилищем
Применяются при API запросах автоматически

$oauth = $amo->fetchAccessToken($code);

При необходимости можно задать oauth данные принудительно, вручную
Данные также будут кешированы автоматически в соответствии с выбранным хранилищем

$amo->setOauth([
	'token_type' => 'Bearer',
	'expires_in' => 86400,
	'access_token' => 'bKSuyc4u6oi...',
	'refresh_token' => 'a89iHvS9uR4...',
	'created_at' => 1597678161
]);

Токен доступа обновляется автоматически, если срок действия refresh_token не истек
При необходимости можно обновить oauth данные по refresh_token принудительно, вручную
Новые oauth данные также будут кешированы автоматически

$oauth = $amo->refreshAccessToken($refresh_token = null); // при передаче null используются кешированные oauth данные

Вызов callback функции при автоматическом обновлении токена доступа

$amo->onAccessTokenRefresh(function($oauth, $query, $response) {
	echo $query->startDate().' - ['.$query->method.'] '.$query->getUrl()."\n";
	print_r($query->post_data);
	echo $query->endDate().' - ['.$response->getCode().'] '. $response->getData(). "\n\n";
	echo "\nRefreshed oauth: \n";
	print_r($oauth);
});
$amo->onAccessTokenRefreshError(function($exc, $query, $response) {
	echo $query->startDate().' - ['.$query->method.'] '.$query->getUrl()."\n";
	print_r($query->post_data);
	echo $query->endDate().' - ['.$response->getCode().'] '. $response->getData(). "\n\n";
	exit('Error refresh token: '.$exc->getMessage().', code: '.$exc->getCode());
});

После первичного выполнения метода fetchAccessToken(), можно пользоваться клиентом в обычном режиме
Повторное выполнение метода fetchAccessToken() или setOauth() необходимо только в случаях, если:

  1. Изменились ключи доступа в приложении
  2. Изменился поддомен amoCRM аккаунта
  3. Истек срок действия refresh_token
  4. Получена ошибка авторизации

Рекомендуется убедиться в отсутствии публичного доступа к папке с кешем - /vendor/ufee/amoapi/src/Cache/
(если используется директория по умолчанию)

Обмен API ключа на код авторизации oAuth

$resp_code = $amo->ajax()->exchangeApiKey(
	$crm_login, 
	$api_hash, 
	$client_id, 
	$client_secret
);
if ($resp_code === 202) {
	// Запрос принят, код авторизации будет отправлен на redirect_uri
}

Инициализация клиента по API-hash

Получение объекта для работы с конкретным аккаунтом

$amo = \Ufee\Amo\Amoapi::setInstance([
    'id' => 123,
    'domain' => 'testdomain',
    'login' => 'test@login',
    'hash' => 'testhash',
    'zone' => 'com', // default: ru
    'timezone' => 'Europe/London', // default: Europe/Moscow
    'lang' => 'en' // default: ru
]);

Включение/выключение автоматической авторизации при ошибке 401
Сессия (cookie) кешируется в файлах

$amo->autoAuth(true); // true/false, рекомендуется true

Работа с клиентом

Включение логирования заросов (Logs/m-Y/domain.log)

$amo->queries->logs(true); // to default path

или

$amo->queries->logs('path_to_log/queries'); // to custom path

Не более 1 запроса за заданное время, в секундах

$amo->queries->setDelay(0.5); // default: 0.15 sec

Запрос /api/v2/account кешируется в файлах, время указывается в секундах

\Ufee\Amo\Services\Account::setCacheTime(1800); // default: 600 sec

Пользовательская отладка запросов (обновлено с вводом oAuth)

$amo->queries->onResponseCode(429, function(\Ufee\Amo\Base\Models\QueryModel $query) {
	echo 'Resp code 429, retry '.$query->retries."\n";
});
$amo->queries->listen(function(\Ufee\Amo\Base\Models\QueryModel $query) {
    $code = $query->response->getCode();
    echo $query->startDate().' - ['.$query->method.'] '.$query->getUrl()."\n";
    print_r($query->headers);
    if ($code === 0) {
        echo $query->response->getError()."\n\n";
    } else {
        print_r(count($query->json_data) ? $query->json_data : $query->post_data);
        echo $query->endDate().' - ['.$query->response->getCode().'] '.$query->response->getData()."\n\n";
    }
});

Кеширование запросов

Хранение кеша возможно в нескольких вариантах

Файловое хранилище

Используется по умолчанию (/vendor/ufee/amoapi/src/Cache/), можно задать свой путь
Создаются кеш-файлы: {path}/{domain}_{hash}.cache
Настоятельно рекомендуется использовать cвой путь для кеширования, в противном случае данные будут УДАЛЕНЫ composer'ом при обновлении на новую версию.

$apiClient->queries->setCacheStorage(
	new \Ufee\Amo\Base\Storage\Query\FileStorage($apiClient, ['path' => 'pull_path_to/cache'])
);

Redis

Поддерживается библиотека phpredis
Формат ключа: {domain}-cache:{hash}

$redis = new \Redis();
$redis->connect('/var/run/redis/redis.sock');
$redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP); // \Redis::SERIALIZER_IGBINARY recommended
$redis->select(5); // switch to specific db

$apiClient->queries->setCacheStorage(
	new \Ufee\Amo\Base\Storage\Query\RedisStorage($apiClient, ['connection' => $redis])
);

Поиск сущностей

Поиск по дополнительному полю

$leads = $amo->leads()->searchByCustomField('Москва', 'Город', 300); // by CF name, max 300
$leads = $amo->leads()->searchByCustomField('Москва', 623425); // by CF id
$companies = $amo->companies()->searchByName('ООО Шарики за Ролики', 100); // by name, max 100
$contacts = $amo->contacts()->searchByEmail('[email protected]', 0); // by email, no max limit
$contacts = $amo->contacts()->searchByPhone('89271002030');

Работа с дополнительными полями

Убрать значение

$entity->cf('Имя поля')->reset();
$entity->cf('Организация')->removeBy('name', 'ИП Петров А.А.');

Получить значение

$entity->cf('Имя поля')->getValue();
$entity->cf('Имя поля')->getValues();
$entity->cf('Имя поля')->getEnums();
$entity->cf('Дата')->format('Y-m-d');
$entity->cf('Дата')->getTimestamp();
$entity->cf('Организация')->getValues();

Задать значение

$entity->cf('Имя поля')->setEnum($enum);
$entity->cf('Имя поля')->setEnums($enums);
$entity->cf('Число')->setValue(5);
$entity->cf('Текст')->setValue('Test');
$entity->cf('Мультисписок')->reset()->setValues(['Мужская одежда', 'Аксессуары']);
$entity->cf('День рождения')->setDate('Y-m-d');
$entity->cf('Дата')->setTimestamp(14867456357);
$entity->cf('Дата')->setDate('Y-m-d');
$entity->cf('Переключатель')->enable();
$entity->cf('Переключатель')->disable();
$entity->cf('Полный адрес')->setCountry('Россия');
$entity->cf('Полный адрес')->setRegion('Чувашская республика');
$entity->cf('Полный адрес')->setCity('Чебоксары');
$entity->cf('Полный адрес')->setIndex(428000);
$entity->cf('Телефон')->setValue('987654321', 'Home');
$entity->cf('Телефон')->setValue('123456789');
$entity->cf('Email')->setValue('[email protected]');
$entity->cf('Мгн. сообщения')->setValue('bestJa', 'Jabber');
$entity->cf('Юр. лицо')->setName('Команда F5');
$entity->cf('Юр. лицо')->setAddress('РФ, ЧР, г.Чебоксары');
$entity->cf('Юр. лицо')->setType(1);
$entity->cf('Юр. лицо')->setInn(123);
$entity->cf('Юр. лицо')->setKpp(456);
$entity->cf('Организация')->addValue([
    'name' => 'ИП Петров А.А.',
    'city' => 'Москва',
    '...' => '...'
]);

Работа с коллекциями

Перебор, поиск и фильтрация

foreach ($amo->leads as $lead) { ... }
$amo->leads->each(function(&$lead) { ... });
$leadsByCf = $amo->leads->find('name', 'Трубы гофрированные');
$leadsBySale = $amo->leads->filter(function($lead) {
    return $lead->sale > 0;
});
$firstLead = $lead->first();
$lastLead = $lead->last();

Сортировка

$leads->sortBy('sale', 'DESC');
$leads->usort(function($a, $b) {});
$leads->uasort(function($a, $b) {});

Дополнительно

$has_contains =  $leads->contains('name', 'Test');
$sale_sum = $leads->sum('sale');
$leads = $leads->transform(function($lead) {
    return [
        'id' => $lead->id,
        'name' => $lead->name
    ];
});
$leads_array = $leads->toArray();

Работа со сделками

Получение всех сделок

$leads = $amo->leads;
$leads = $amo->leads()->recursiveCall();
$leads = $amo->leads()->call(); // первые 500

Получение по дате последнего изменения

$leads = $amo->leads()
             ->modifiedFrom('Y-m-5 09:20:00') // по дате, с 5 числа текущего месяца, с 9:20 утра
             ->modifiedFrom(1528188143) // или по timestamp
             ->maxRows(1000)
             ->listing();

Получение по ID

$lead = $amo->leads()->find($id); // array|integer

Получение сделок с дополнительным условием

$lead = $amo->leads()->where('key', $val)->recursiveCall();

Связанные сущности по сделке

$contact = $lead->contact;
$contacts = $lead->contacts;
$company = $lead->company;
$tasks = $lead->tasks;
$notes = $lead->notes;

Создание сделок

$leads = [
    $amo->leads()->create(),
    $amo->leads()->create()
];
$leads[0]->name = 'Amoapi v7 - 1';
$leads[1]->name = 'Amoapi v7 - 2';
$amo->leads()->add($leads);

$lead = $amo->leads()->create();
$lead->name = 'Amoapi v7';
$lead->attachTag('Amoapi');
$lead->pipeline_id = $amo->account->pipelines->main();
$lead->status_id = $lead->pipeline->statuses->first();
$lead->responsible_user_id = $amo->account->currentUser->id;
$lead->sale = 100500;
$lead->cf('Число')->setValue(5);
$lead->cf('Текст')->setValue('Test');
$lead->cf('Мультисписок')->reset()->setValues(['Мужская одежда', 'Аксессуары']);
$lead->cf('Дата')->setValue(date('Y-m-d'));
$lead->cf('Переключатель')->disable();
$lead->save();

Создание сделки из контакта

$lead = $contact->createLead();
$lead->name = 'Amoapi v7';
$lead->save();

Копирование сделки

$copy = clone $lead;
$copy->name = 'New lead';
$copy->save();

Работа с контактами

Получение всех контактов

$contacts = $amo->contacts;
$contacts = $amo->contacts()->recursiveCall();
$contacts = $amo->contacts()->call(); // первые 500

Получение по ID

$contact = $amo->contacts()->find($id); // array|integer

Получение контактов с дополнительным условием

$contacts = $amo->contacts()->where('key', $val)->recursiveCall();

Связанные сущности по контакту

$leads = $contact->leads;
$company = $contact->company;
$tasks = $lead->tasks;
$notes = $lead->notes;

Создание контактов

$contacts = [
    $amo->contacts()->create(),
    $amo->contacts()->create()
];
$contacts[0]->name = 'Amoapi v7 - 1';
$contacts[1]->name = 'Amoapi v7 - 2';
$amo->contacts()->add($contacts);

$contact = $amo->contacts()->create();
$contact->name = 'Amoapi v7';
$contact->attachTags(['Amoapi', 'Test']);
$contact->cf('Телефон')->setValue('987654321', 'Home');
$contact->cf('Телефон')->setValue('123456789');
$contact->cf('Email')->setValue('[email protected]');
$contact->save();

Создание контакта из сделки

$contact = $lead->createContact();
$contact->name = 'Amoapi v7';
$contact->save();

Копирование контакта

$copy = clone $contact;
$copy->name = 'New contact';
$copy->save();

Работа с компаниями

Получение всех компаний

$companies = $amo->companies;
$companies = $amo->companies()->recursiveCall();
$companies = $amo->companies()->call(); // первые 500

Получение по ID

$company = $amo->companies()->find($id); // array|integer

Получение компаний с дополнительным условием

$companies = $amo->companies()->where('key', $val)->recursiveCall();

Связанные сущности по компании

$leads = $company->leads;
$contacts = $company->contacts;
$tasks = $lead->tasks;
$notes = $lead->notes;

Создание компаний

$companys = [
    $amo->companies()->create(),
    $amo->companies()->create()
];
$companys[0]->name = 'Amoapi v7 - 1';
$companys[1]->name = 'Amoapi v7 - 2';
$amo->companies()->add($companys);

$company = $amo->companies()->create();
$company->name = 'Amoapi v7';
$company->save();

Создание компании из контакта или сделки

$company = $contact->createCompany();
$company = $lead->createCompany();
$company->name = 'Amoapi v7';
$company->save();

Копирование компании

$copy = clone $company;
$copy->name = 'New company';
$copy->save();

Работа с задачами

Получение всех задач

$tasks = $amo->tasks;
$tasks = $amo->tasks()->recursiveCall();
$tasks = $amo->tasks()->call(); // первые 500

Получение по ID

$task = $amo->tasks()->find($id); // array|integer

Получение задач с дополнительным условием

$tasks = $amo->tasks()->where('key', $val)->recursiveCall();

Создание задач

$tasks = [
    $amo->tasks()->create(),
    $amo->tasks()->create()
];
$tasks[0]->text = 'Amoapi v7 - 1';
$tasks[0]->element_type = 3;
$tasks[0]->element_id = 34762721;
$tasks[1]->text = 'Amoapi v7 - 2';
$tasks[1]->element_type = 2;
$tasks[1]->element_id = 34762720;
$amo->tasks()->add($tasks);

$task = $amo->tasks()->create();
$task->text = 'Amoapi v7';
$task->element_type = 1;
$task->element_id = 34762725;
$task->save();

Создание задачи из контакта, сделки или компании

$task = $contact->createTask($type = 1);
$task = $lead->createTask($type = 1);
$task = $company->createTask($type = 1);
$task->text = 'Amoapi v7';
$task->element_type = 1;
$task->element_id = 34762725;
$task->save();

Получение родительского контакта, сделки или компании

$contact = $task->linkedContact;
$lead = $task->linkedLead;
$comapny = $task->linkedCompany;

Работа с примечаниями

Получение всех примечаний

$notes = $amo->notes;
$notes = $amo->notes()->where('type', 'contact')->recursiveCall();
$notes = $amo->notes()->where('type', 'lead')->call(); // первые 500

Получение примечаний по ID и типу сущности

$note = $amo->notes()->find($id, 'lead');

Получение примечаний с дополнительным условием

$notes = $amo->notes()->where('key', $val)->recursiveCall();

Создание примечаний

$notes = [
    $amo->notes()->create(), 
    $amo->notes()->create()
];
$notes[0]->note_type = 4;
$notes[0]->text = 'Amoapi v7 - 1';
$notes[0]->element_type = 3;
$notes[0]->element_id = 34762721;
$notes[1]->note_type = 4;
$notes[1]->text = 'Amoapi v7 - 2';
$notes[1]->element_type = 2;
$notes[1]->element_id = 34762720;
$amo->notes()->add($notes);

$note = $amo->notes()->create();
$note->note_type = 4;
$note->text = 'Amoapi v7';
$note->element_type = 1;
$note->element_id = 34762725;
$note->save();

Создание примечания из контакта, сделки или компании

$note = $contact->createNote($type = 4);
$note = $lead->createNote($type = 4);
$note = $company->createNote($type = 4);
$note->text = 'Amoapi v7';
$note->element_type = 2;
$note->element_id = 34762728;
$note->save();

Закрепление/открепление примечаний (note type 4)

$note->setPinned(true); // true/false

Получение содержимого файла (note type 5)

$contents = $note->getAttachment();

Получение родительского контакта, сделки или компании

$contact = $note->linkedContact;
$lead = $note->linkedLead;
$comapny = $note->linkedCompany;

Работа со списками

Получение всех списков (каталогов)

$catalogs = $amo->catalogs;

Получение по ID

$catalog = $amo->catalogs()->find($id); // array|integer

Получение списков с дополнительным условием

$catalogs = $amo->catalogs()->where('key', $val)->call();

Связанные сущности по списку

$elements = $catalog->elements;

Создание списков

$catalogs = [
    $amo->catalogs()->create(),
    $amo->catalogs()->create()
];
$catalogs[0]->name = 'Amoapi v7 - 1';
$catalogs[1]->name = 'Amoapi v7 - 2';
$amo->catalogs()->add($catalogs);

$catalog = $amo->catalogs()->create();
$catalog->name = 'Amoapi v7';
$catalog->save();

Удаление списков

$amo->catalogs()->delete($catalogs); // array|integer
$catalog->delete();

Работа с элементами каталога (товарами)

Получение товаров

$element = $amo->catalogElements()->find($id);
$elements = $amo->catalogElements()->where('catalog_id', 1234)->call();
$elements = $catalog->elements;

Добавление товаров

$element = $amo->catalogElements()->create();
$element->catalog_id = 1234;

или

$element = $catalog->createElement();
$element->name = 'Холодильник LG';
$element->cf('Артикул')->setValue('ML-4675');
$element->cf('Количество')->setValue(100);
$element->cf('Цена')->setValue(38500);
$element->save();

Обновление товаров

$element->cf('Скидка')->setValue(5);
$element->save();

Связанные сущности по товару

$catalog = $element->catalog;
$leads = $element->leads;

Удаление товаров

$amo->elements()->delete($elements); // array|integer
$catalog->elements->delete(); // удаление всех товаров каталога
$element->delete();

Прикрепление товаров к сделке

$lead->attachElement($catalog->id, $element->id, $count = 1);

Работа с покупателями

Получение всех покупателей

$customers = $amo->customers;
$customers = $amo->customers()->recursiveCall();
$customers = $amo->customers()->call(); // первые 500

Получение по ID

$customer = $amo->customers()->find($id); // array|integer

Получение покупателей с дополнительным условием

$customer = $amo->customers()->where('key', $val)->recursiveCall();

Связанные сущности покупателя

$contact = $customer->contact;
$contacts = $customer->contacts;
$company = $customer->company;
$tasks = $customer->tasks;
$notes = $customer->notes;
$transactions = $customer->transactions;

Создание покупателей

$customer = $amo->customers()->create();
$customer->name = 'Amoapi v7';
$customer->next_date = time();
$customer->next_price = 100;
$customer->responsible_user_id = $amo->account->currentUser->id;
$customer->cf('Число')->setValue(5);
$customer->cf('Текст')->setValue('Test');
$customer->cf('Мультисписок')->reset()->setValues(['Мужская одежда', 'Аксессуары']);
$customer->cf('Дата')->setValue(date('Y-m-d'));
$customer->cf('Переключатель')->disable();
$customer->save();

Создание покупателя из контакта

$customer = $contact->createCustomer();
$customer->name = 'Amoapi v7';
$customer->next_date = time();
$customer->save();

Удаление покупателей

$amo->customers()->delete($customers); // array|integer
$customer->delete();

Работа с покупками

Получение транзакций (покупок)

$transactions = $amo->transactions;
$transactions = $customer->transactions;

Добавление транзакций

$transaction = $amo->transactions()->create();
$transaction->customer_id = 1234;

или

$transaction = $customer->createTransaction();
$transaction->price = 1500;
$transaction->save();

Обновление комментариев транзакций покупателя

$transaction->comment = 'Тест';
$transaction->save();

Удаление транзакций покупателей

$amo->transactions()->delete($transactions); // array|integer
$customer->transactions->delete(); // удаление всех покупок покупателя
$transaction->delete(); // удаление покупки

Работа с веб-хуками

Получение вебхуков (webhooks)

$webhooks = $amo->webhooks;

Добавление вебхуков

$result = $amo->webhooks()->subscribe('http://site.ru/handler/', ['add_lead', 'update_contact', 'responsible_lead']);

Удаление вебхуков

$result = $amo->webhooks()->unsubscribe('http://site.ru/handler/', ['update_contact', 'responsible_lead']);

Работа с frontend методами

Скачивание файла из примечания

$contents = $amo->ajax()->getAttachment('AbCd_attach_name.zip');

Выполнение произвольных запросов

$amo->ajax()->get($url = '/ajax/example', $args = []);
$amo->ajax()->post($url = '/ajax/example', $data = [], $args = [], $post_type = 'raw OR json');
$amo->ajax()->postJson($url = '/ajax/example', $data = [], $args = []);
$amo->ajax()->patch($url = '/ajax/example', $data = [], $args = []);

Работа с Salesbot

$bots = $amo->salesbots()->get($page = 1, $limit = 250);
$bots = $amo->salesbots;

$start = $amo->salesbots()->start($bot_id, $entity_id, $entity_type = 2);
$stop = $amo->salesbots()->stop($bot_id, $entity_id, $entity_type = 2);

amoapi's People

Contributors

bigperson avatar m4tlch avatar mkhk6 avatar ufee avatar vladimir-proger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

amoapi's Issues

oAuth 2.0

Приветствую, будет ли добавлена поддержка oAuth 2.0? в данный момент без кода авторизации амо бьет по лицу сапогом..., сам ответил на свои вопросы, не внимательно читал документацию

Invalid response code: 202

$response = $ufeeApi->ajax()->post('/ajax/merge/contacts/save', $query);

Стоит добавить поддержку 202 ответа

throw new \Exception('Account not found: '.$account_id);

Постоянно возникает ошибка Account not found: 4 во время setInstance при протухших ранее доступах.
Помогает только удаление кеша.
Отсюда следует еще одна проблема, нельзя задать путь кеша до вызова setInstance. И нет методов для удаления кеша отдельного инстанса

Trace:
image

Не работает получение сделок с дополнительным условием

$lead = $amo->leads()->where('key', $val)->recursiveCall();
из примера не работает, пытаюсь сделать выборку по status_id, выдает всё равно абсолютно все сделки, пробовал даже по name, все равно не получается.

$lead = $amo->leads()->where('name', $name)->recursiveCall(); //выгружает все сделки
$lead = $amo->leads()->where('status_id', $idstatus)->recursiveCall(); //выгружает все сделки

$lead = $amo->leads()->where('id', $id)->recursiveCall(); //выгружает нужную сделку
этот код аналогичен $lead = $amo->leads()->find($id);, который тоже успешно выполняется.

Не понятно почему так происходит если вот по доп.полям выборка хорошо работает и выгружает только то, что подпадает под выборку.
$leads = $amo->leads()->searchByCustomField('Москва', 623425); // by CF id

Ошибка 401 при вызове fetchAccessToken()

Получаю следующую ошибку при попытке авторизоваться.

{
"title": "Некорректный клиент",
"type": "https://developers.amocrm.ru/v3/errors/OAuthProblemJson",
"status": 401,
"detail": "Авторизация клиента не прошла"
}

Шаги:

  1. Получаю ссылку для авторизации так $amo->getOauthUrl($arg = ['mode' => 'popup', 'state' => 'amoapi']);
  2. На стороне amocrm выбираю для какого аккаунта предоставить доступы
  3. Далее следует редирект с кодом на сайт, где получаю code из get параметров
  4. далее пытаюсь получить accessToken - $amo->fetchAccessToken($code);
    В итоге получаю ошибку выше.

Подскажите, в чем может быть проблема и куда смотреть?

Дополнительное поле по его id

Не всегда удобно заполнять по названию поля, клиент может название чуть изменить и вся интеграция слетает) Было бы удобно использовать как название, так и айдишник нужного поля

$lead->cf(284441)->setValue($value);

Массовое добавление/редатирование сущностей в один запрос

Привет!
Спасибо за отличную библиотеку, использую ее вместо стандартной амовской.
Правда сейчас наткнулся на одно ограничение.
Мне нужно отредактировать много сделок/контактов скопом.
Читая документацию, предполагал что подобный функционал есть

$contacts = [ $amo->contacts()->create(), $amo->contacts()->create() ]; $contacts[0]->name = 'Amoapi v7 - 1'; $contacts[1]->name = 'Amoapi v7 - 2'; $amo->contacts()->add($contacts);

Но, к сожалению нет, библиотека это отправляет двумя отдельными запросами.
Есть какое-то штатное решение для этой ситуации или же надо допиливать самостоятельно.
Спасибо!

Undefined index: created_at

При использовании Oauthapi::setOauthStorage(new \Ufee\Amo\Base\Storage\Oauth\FileStorage(['path' => $cachePath]));

Получаем ошибку
vendor/ufee/amoapi/src/Api/Oauth/Query.php

$expire_time = ($oauth['created_at']+$oauth['expires_in'])-time();

Ошибка с данными типа Integer

Подскажите, пожалуйста.
Использую авторизацию oAuth и пытаюсь создать например контакт через новое API, обращаясь к '/api/v4/contacts', используя функцию произвольного запроса, но возникает ошибка валидации для данных типа Integer. С другими типами данных проблем нет. Как это можно решить? Создание контакта - это просто пример. Мне требуется работать с неразобранным, но эта ошибка повторяется и при создании контакта

// Пример кода
$input['contact'][] = [
'name' => 'test77',
'created_at' => time(),
];
$amo->ajax()->post($url = '/api/v4/contacts', $input['contact']);

// Пример ошибки:
{"validation-errors":[{"request_id":"0","errors":[{"code":"InvalidType","path":"created_at","detail":"This value should be of type int."}]}],"title":"Bad Request","type":"https://httpstatus.es/400","status":400,"detail":"Request validation failed"}

Как создать задачу?

В документации у вас написан пример:
$task = $amo->tasks()->create();
$task->text = 'Amoapi v7';
$task->element_type = 1;
$task->element_id = 34762725;
$task->save();

Что такое element type и element_id? Для создания задачи в этой crm достаточно передать text и complete_till, зачем нужны остальные параметры?

updated_at в теле сущностей

Часто возникает ошибка при обновлении

{"update":{"25063315":"Last modified date is older than in database"}}

Указывать update_at = time() + {second} как будто костыль, который не всегда помогает

В апи доке этот параметр необязательный, но если тут попытаться задать ему null - будет эксепшн, а по умолчанию в либе ему задается значение time(), зачем?

Насколько понимаю, если не передавать значение метки обновления, то все будет ок

Вопрос по первому получению токенов.

`require_once 'vendor/autoload.php';

use \Ufee\Amo\Oauthapi;
use \Ufee\Amo\Base\Storage\Oauth\FileStorage;

$amo = Oauthapi::setInstance([
'domain' => 'poddomain.amocrm.ru',
'client_id' => '....',
'client_secret' => '.....',
'redirect_uri' => 'https://site.ru',
'zone' => 'ru',
'timezone' => 'Europe/Moscow',
'lang' => 'ru'
]);

//
$amo = Oauthapi::getInstance('......');

$first_auth_url = $amo->getOauthUrl($arg = ['mode' => 'popup', 'state' => 'amoapi']);
;

$code = '.......';
$oauth = $amo->fetchAccessToken($code);
print_r($oauth);`
print_r($oauth) вроде как должен вывести время, когда захешировались токены так? Ничего не приходит, может чего написал не так? Второй вопрос, в папке cache создается папка с названием домена, но в ней ничего нет, как мне посмотреть, что вообще сохранилось в итоге?

Api v4

Планируется ли дополнить/заменить методы из новой версии api?

Выполнение Ajax запросов не работает 403

Выполнение произвольных запросов не работает:

$result = $this->ufeeamo->ajax()->post('/ajax/settings/custom_fields/', [
           'action' => 'apply_changes',
            'element_type' => 2,
            'groups' => [
                [
                    'name' => 'test Api',
                    'id' => ''
                ]
            ]
        ]);

403 ошибка
$query->setHeader('X-Requested-With', 'XMLHttpRequest') не отрабатывает должным образом, в результате заголовок не передается.

Дамп запроса:

* Hostname subdomain.amocrm.ru was found in DNS cache
*   Trying 23.111.109.17...
* TCP_NODELAY set
* Connected to subdomain.amocrm.ru (23.111.109.17) port 443 (#0)
* ALPN, offering http/1.1
* ignoring certificate verify locations due to disabled peer verification
* NPN, negotiated HTTP1.1
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; CN=*.amocrm.ru
*  start date: Jul  2 17:12:23 2019 GMT
*  expire date: Aug 31 14:08:50 2020 GMT
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> POST /ajax/settings/custom_fields/ HTTP/1.1
Host: subdomain.amocrm.ru
User-Agent: Amoapi v.8 (subdomain/ru)
Accept: */*
Cookie: session_id=****
Content-Length: 91
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 91 out of 91 bytes
< HTTP/1.1 403 Forbidden
< Server: nginx
< Date: Sat, 04 Apr 2020 08:55:32 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< Set-Cookie: user_lang=ru; expires=Fri, 04-Apr-2025 08:55:32 GMT; Max-Age=157766400; path=/; domain=.amocrm.ru
< X-Runtime-Generated: 0,0722
< 
* Connection #0 to host subdomain.amocrm.ru left intact

Exception : Invalid response code: 403

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.