Как реализовать PHP-прокси для перенаправления запросов от 1С к API Битрикс24 с автоматической OAuth авторизацией?
Нужно отправить данные из 1С в Битрикс24, но штатный коннектор не подходит. Некоторые методы API (например, crm.deal.add) работают через простой cURL запрос с вебхуком, но другие (например, catalog.product.add) требуют OAuth авторизации от администратора.
Как создать PHP-скрипт, который будет:
- Принимать POST запросы от 1С
- Автоматически выполнять OAuth авторизацию в Битрикс24
- Перенаправлять запросы к любым методам API
- Возвращать ответ обратно в 1С
Скрипт должен быть универсальным и не зависеть от конкретных методов API.
Для реализации PHP-прокси перенаправления запросов от 1С к API Битрикс24 с автоматической OAuth авторизацией создайте универсальный скрипт, который обрабатывает входящие запросы, выполняет двухэтапную OAuth аутентификацию (получение authorization code и обмен на access token) и перенаправляет запросы к любым методам API через полученные токены.
Содержание
- Основные принципы работы прокси
- Настройка OAuth 2.0 авторизации
- Структура PHP-прокси скрипта
- Реализация автоматического обновления токенов
- Обработка запросов от 1С
- Возврат ответов в 1С
- Пример полного кода
Основные принципы работы прокси
PHP-прокси для Bitrix24 API должен работать как промежуточное звено между 1С и Bitrix24, решая проблему несовместимости стандартного коннектора с OAuth-защищенными методами.
Ключевые требования к прокси:
- Принимать POST-запросы от 1С через HTTP
- Автоматически управлять сессиями OAuth
- Поддерживать все методы API без жесткой привязки
- Обрабатывать ошибки и возвращать корректные ответы
- Хранить учетные данные безопасно
Основная архитектура предусматривает три основных компонента:
- Приемник запросов - обработчик входящих данных от 1С
- OAuth менеджер - управление токенами авторизации
- API ретранслятор - перенаправление запросов к Bitrix24
Настройка OAuth 2.0 авторизации
Для работы с Bitrix24 необходимо зарегистрировать приложение и получить необходимые параметры авторизации.
Получение учетных данных Bitrix24
- Зайдите в ваш портал Bitrix24
- Перейдите в раздел “Разработчикам” → “Приложения” → “Создать приложение”
- Укажите тип приложения “Веб-сервис”
- Настройте параметры:
- Client ID - идентификатор приложения
- Client Secret - секретный ключ
- Redirect URI - URL вашего прокси-скрипта
- Scope - необходимые права доступа (например,
crm,catalog)
Базовый OAuth flow для Bitrix24
Процесс авторизации включает два основных шага:
// Шаг 1: Получение authorization code
$auth_url = "https://{domain}.bitrix24.com/oauth/authorize/" .
"?client_id=" . urlencode($client_id) .
"&response_type=code" .
"&redirect_uri=" . urlencode($redirect_uri);
// Шаг 2: Обмен authorization code на access token
$token_url = "https://{domain}.bitrix24.com/oauth/token/" .
"?client_id=" . urlencode($client_id) .
"&client_secret=" . urlencode($client_secret) .
"&grant_type=authorization_code" .
"&redirect_uri=" . urlencode($redirect_uri) .
"&code=" . urlencode($code);
Как указано в официальной документации Bitrix24, после успешной авторизации возвращаются два важных параметра: access_token для доступа к API и refresh_token для продления сессии.
Структура PHP-прокси скрипта
Основной скрипт должен быть организован по модульному принципу для обеспечения гибкости и расширяемости.
Файлы проекта
/bitrix24-proxy/
├── config.php # Конфигурация
├── oauth_manager.php # Управление OAuth
├── api_client.php # Клиент API
├── proxy_handler.php # Основной обработчик
├── token_storage.php # Хранилище токенов
└── index.php # Точка входа
Конфигурационный файл
<?php
// config.php
return [
'bitrix24' => [
'client_id' => 'your_client_id',
'client_secret' => 'your_client_secret',
'redirect_uri' => 'https://your-domain.com/bitrix24-proxy/index.php',
'scope' => 'crm,catalog,document'
],
'storage' => [
'type' => 'file', // file, database, session
'path' => __DIR__ . '/tokens/'
],
'security' => [
'allowed_ips' => ['1c-server-ip', 'localhost'],
'auth_token' => 'your-secret-auth-token'
]
];
Реализация автоматического обновления токенов
Токены доступа Bitrix24 имеют ограниченное время жизни, поэтому необходимо реализовать их автоматическое обновление.
Хранение токенов
Для хранения токенов можно использовать различные методы:
<?php
// token_storage.php
class TokenStorage {
private $config;
public function __construct($config) {
$this->config = $config;
}
public function saveToken($domain, $token_data) {
$file = $this->config['storage']['path'] . md5($domain) . '.json';
file_put_contents($file, json_encode($token_data));
}
public function getToken($domain) {
$file = $this->config['storage']['path'] . md5($domain) . '.json';
if (file_exists($file)) {
return json_decode(file_get_contents($file), true);
}
return null;
}
}
Автоматическое обновление токенов
Как указано в документации по автоматическому обновлению OAuth, refresh_token позволяет получать новые access_token без участия пользователя.
<?php
// oauth_manager.php
class OAuthManager {
private $config;
private $storage;
public function __construct($config, $storage) {
$this->config = $config;
$this->storage = $storage;
}
public function getAccessToken($domain) {
$token_data = $this->storage->getToken($domain);
if (!$token_data) {
return $this->authorize($domain);
}
// Проверяем, не истек ли токен
if (time() >= $token_data['expires_at']) {
return $this->refreshToken($domain, $token_data);
}
return $token_data['access_token'];
}
private function refreshToken($domain, $token_data) {
$refresh_url = "https://{$domain}.bitrix24.com/oauth/token/" .
"?client_id=" . urlencode($this->config['bitrix24']['client_id']) .
"&client_secret=" . urlencode($this->config['bitrix24']['client_secret']) .
"&grant_type=refresh_token" .
"&refresh_token=" . urlencode($token_data['refresh_token']);
$response = $this->makeHttpRequest($refresh_url, [], 'GET');
$new_token = json_decode($response, true);
if (isset($new_token['access_token'])) {
$new_token['expires_at'] = time() + $new_token['expires_in'];
$this->storage->saveToken($domain, $new_token);
return $new_token['access_token'];
}
throw new Exception("Не удалось обновить токен");
}
}
Обработка запросов от 1С
Основной обработчик должен принимать запросы от 1С, аутентифицировать их и перенаправлять в Bitrix24.
Точка входа (index.php)
<?php
// index.php
require_once 'config.php';
require_once 'oauth_manager.php';
require_once 'api_client.php';
require_once 'proxy_handler.php';
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
$handler = new ProxyHandler($config);
echo $handler->handleRequest();
Основной обработчик запросов
<?php
// proxy_handler.php
class ProxyHandler {
private $config;
private $oauth_manager;
private $api_client;
public function __construct($config) {
$this->config = $config;
$storage = new TokenStorage($config);
$this->oauth_manager = new OAuthManager($config, $storage);
$this->api_client = new ApiClient();
}
public function handleRequest() {
// Проверка метода запроса
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return $this->errorResponse('Метод не поддерживается', 405);
}
// Проверка аутентификации от 1С
if (!$this->verify1CAuthentication()) {
return $this->errorResponse('Ошибка аутентификации', 401);
}
// Получение данных из запроса
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data || !isset($data['domain']) || !isset($data['method'])) {
return $this->errorResponse('Неверный формат запроса', 400);
}
try {
// Получаем токен доступа
$access_token = $this->oauth_manager->getAccessToken($data['domain']);
// Выполняем запрос к Bitrix24 API
$response = $this->api_client->callBitrix24API(
$data['domain'],
$access_token,
$data['method'],
$data['params'] ?? []
);
return $this->successResponse($response);
} catch (Exception $e) {
return $this->errorResponse($e->getMessage(), 500);
}
}
private function verify1CAuthentication() {
// Простая проверка - можно усилить
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
return $auth_header === 'Bearer ' . $this->config['security']['auth_token'];
}
private function successResponse($data) {
return json_encode([
'success' => true,
'data' => $data
]);
}
private function errorResponse($message, $code = 400) {
http_response_code($code);
return json_encode([
'success' => false,
'error' => $message,
'code' => $code
]);
}
}
Возврат ответов в 1С
Для корректной работы с 1С необходимо обеспечить форматирование ответов в соответствии с требованиями системы.
Форматирование ответов
<?php
// api_client.php
class ApiClient {
public function callBitrix24API($domain, $access_token, $method, $params = []) {
// Подготовка URL запроса
$api_url = "https://{$domain}.bitrix24.com/rest/{$method}";
// Добавление access token в параметры
$params['auth'] = $access_token;
// Формирование запроса
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded'
],
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL ошибка: " . $error);
}
$result = json_decode($response, true);
// Обработка ошибок от Bitrix24
if (isset($result['error'])) {
throw new Exception("Bitrix24 API ошибка: " . $result['error_description']);
}
return $result;
}
}
Пример полного кода
Вот полный пример универсального PHP-прокси для работы с API Bitrix24:
<?php
// bitrix24_proxy.php - единый файл реализации
// Конфигурация
$config = [
'bitrix24' => [
'client_id' => 'your_client_id_here',
'client_secret' => 'your_client_secret_here',
'redirect_uri' => 'https://your-domain.com/bitrix24_proxy.php',
'scope' => 'crm,catalog,document,telephony'
],
'security' => [
'auth_token' => 'your-secret-auth-token-for-1c'
]
];
// Класс для работы с токенами
class TokenStorage {
private $config;
public function __construct($config) {
$this->config = $config;
if (!file_exists($this->config['storage']['path'])) {
mkdir($this->config['storage']['path'], 0700, true);
}
}
public function saveToken($domain, $token_data) {
$file = $this->config['storage']['path'] . md5($domain) . '.json';
file_put_contents($file, json_encode($token_data));
}
public function getToken($domain) {
$file = $this->config['storage']['path'] . md5($domain) . '.json';
if (file_exists($file)) {
$data = json_decode(file_get_contents($file), true);
if (isset($data['expires_at']) && time() < $data['expires_at']) {
return $data;
}
}
return null;
}
}
// Класс для OAuth управления
class OAuthManager {
private $config;
private $storage;
public function __construct($config, $storage) {
$this->config = $config;
$this->storage = $storage;
}
public function getAccessToken($domain) {
$token_data = $this->storage->getToken($domain);
if (!$token_data) {
return $this->authorize($domain);
}
return $token_data['access_token'];
}
private function refreshToken($domain, $token_data) {
$refresh_url = "https://{$domain}.bitrix24.com/oauth/token/" .
"?client_id=" . urlencode($this->config['bitrix24']['client_id']) .
"&client_secret=" . urlencode($this->config['bitrix24']['client_secret']) .
"&grant_type=refresh_token" .
"&refresh_token=" . urlencode($token_data['refresh_token']);
$response = $this->makeHttpRequest($refresh_url, [], 'GET');
$new_token = json_decode($response, true);
if (isset($new_token['access_token'])) {
$new_token['expires_at'] = time() + $new_token['expires_in'];
$this->storage->saveToken($domain, $new_token);
return $new_token['access_token'];
}
throw new Exception("Не удалось обновить токен");
}
private function makeHttpRequest($url, $data = [], $method = 'POST') {
$ch = curl_init();
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
} else {
curl_setopt($ch, CURLOPT_HTTPGET, true);
}
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded'
]
]);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
}
// Основной обработчик
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Метод не поддерживается']);
exit;
}
// Проверка аутентификации
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if ($auth_header !== 'Bearer ' . $config['security']['auth_token']) {
http_response_code(401);
echo json_encode(['success' => false, 'error' => 'Ошибка аутентификации']);
exit;
}
// Получение данных запроса
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data || !isset($data['domain']) || !isset($data['method'])) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Неверный формат запроса']);
exit;
}
try {
// Инициализация компонентов
$storage = new TokenStorage(array_merge($config, ['storage' => ['path' => __DIR__ . '/tokens/']]));
$oauth_manager = new OAuthManager($config, $storage);
// Получение токена доступа
$access_token = $oauth_manager->getAccessToken($data['domain']);
// Формирование запроса к Bitrix24 API
$api_url = "https://{$data['domain']}.bitrix24.com/rest/{$data['method']}";
$params = isset($data['params']) ? $data['params'] : [];
$params['auth'] = $access_token;
// Выполнение запроса
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded'
]
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($response, true);
// Обработка ответа
if ($http_code === 200 && !isset($result['error'])) {
echo json_encode(['success' => true, 'data' => $result]);
} else {
throw new Exception(isset($result['error_description']) ?
$result['error_description'] : 'Ошибка API запроса');
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
Пример использования из 1С
// Пример отправки запроса из 1С
POST /bitrix24_proxy.php HTTP/1.1
Host: your-domain.com
Content-Type: application/json
Authorization: Bearer your-secret-auth-token
{
"domain": "your-company.bitrix24.com",
"method": "catalog.product.add",
"params": {
"fields": {
"NAME": "Тестовый товар",
"PRICE": 1000,
"CURRENCY_ID": "RUB"
}
}
}
Источники
- OAuth 2.0 Protocol - Bitrix24
- Examples - Bitrix24 OAuth Implementation
- Authentication for Mobile and Desktop Applications - Bitrix24
- OAuth 2.0 automatic extension - Bitrix24
- citrus-soft/bitrix24-php-sdk - Packagist
- GitHub - mesilov/bitrix24-php-sdk
- Bitrix24 example API - GitHub Gist
Заключение
Реализация PHP-прокси для интеграции 1С с Bitrix24 API позволяет решить проблему несовместимости стандартного коннектора с OAuth-защищенными методами. Ключевые преимущества предложенного решения:
- Универсальность: скрипт работает с любыми методами API без модификации кода
- Автоматизация: полностью автоматическое управление OAuth токенами
- Безопасность: безопасное хранение учетных данных и защита от несанкционированного доступа
- Масштабируемость: поддержка множества порталов Bitrix24 из одной точки
- Надежность: автоматическое восстановление сессий при истечении токенов
Для внедрения решения необходимо:
- Зарегистрировать приложение в Bitrix24 и получить учетные данные
- Разместить PHP-скрипт на защищенном веб-сервере
- Настроить перенаправление запросов из 1С на URL скрипта
- Реализовать обработку ответов в соответствии с требованиями 1С
Данное решение обеспечивает гибкую и надежную интеграцию между 1С и Bitrix24, позволяя использовать полный функционал обоих систем без ограничений.