В этой статье расскажу как интегрировать сервисы СДЭК на сайт интернет-магазин, чтобы можно было выбирать города, пункты выдачи, и отправлять заявку в СДЭК на формирование заказа.
Сначала нужно войти в свой аккаунт СДЭК по ссылке https://lk.cdek.ru/user/login. Далее нужно заключить договор со СДЭК и получить ключи для работы с API. В этот шаг углубляться не будем, в интернете много инфы как это сделать. Перейдем к технической части.
Ключи доступы
После подписания договора в личном кабинете будут доступны ключи для интеграции. Их должно быть два – Client ID и Client Secret.
Документация
Официальная подробная документация по СДЭК API находится тут https://apidoc.cdek.ru/
Бэкенд
Теперь имея ключи, можем создать php файл обработчик (cdek.php) запросов в СДЭК. Допустим у нас есть два селекта на сайте: с выбором города и пвз для доставки. В обработчике напишем метод который будет определять что мы запрашиваем, города или список ПВЗ.
Для обращения к API СДЭК нужно иметь токен авторизации. Поэтому, перед тем как сделать запрос, сначала пройдем авторизацию, и будем хранить токен авторизации в файле, чтобы в дальнейшем все запросы делать с этим токеном:
<?php
header("Content-Type: application/json");
$client_id = "YOUR_CLIENT_ID";
$client_secret = "YOUR_CLIENT_SECRET";
$cache_file = __DIR__ . "/cdek_token_cache.json";
// функция получения токена с кэшем
function getCdekToken($client_id, $client_secret, $cache_file) {
// если токен есть в кеше и не истек
if (file_exists($cache_file)) {
$cache = json_decode(file_get_contents($cache_file), true);
if (isset($cache["access_token"], $cache["expires_at"]) && time() < $cache["expires_at"]) { return $cache["access_token"]; } } // получаем новый токен $fields = http_build_query([ "grant_type" => "client_credentials",
"client_id" => $client_id,
"client_secret" => $client_secret
]);
$ch = curl_init("https://api.cdek.ru/v2/oauth/token");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/x-www-form-urlencoded",
"Accept: application/json"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (!isset($data["access_token"], $data["expires_in"])) {
return null;
}
$data["expires_at"] = time() + $data["expires_in"] - 30;
file_put_contents($cache_file, json_encode($data));
return $data["access_token"];
}
// получаем токен
$token = getCdekToken($client_id, $client_secret, $cache_file);
if (!$token) {
echo json_encode(["error" => "Не удалось получить токен"]);
exit;
}
// получаем метод из формы
$method = $_GET["method"] ?? "cities";
switch ($method) {
case "cities":
$url = "https://api.cdek.ru/v2/location/cities";
break;
case "pvz":
$city_code = $_GET["city_code"] ?? "";
if (!$city_code) {
echo json_encode(["error" => "Не указан city_code"]);
exit;
}
$url = "https://api.cdek.ru/v2/deliverypoints?city_code=$city_code";
break;
default:
echo json_encode(["error" => "Неизвестный метод"]);
exit;
}
// запрос в СДЭК
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $token"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Фронтенд
Теперь напишем функции для получения городов и пунктов выдачи по API:
async function fetchCities() {
const res = await fetch("/apiUrl/cdek.php?method=cities");
const data = await res.json();
const select = $("#citySelect");
select.html("<option disabled selected>Выберите город</option>");
const filteredCities = data.filter(city => city.longitude !== 0 && city.latitude !== 0);
const options = filteredCities.map(city =>
$('<option>', {
'data-code': city.code,
value: `${city.code}, ${city.city}`,
text: city.city
})
);
select.append(options);
}
async function fetchPvz(cityCode) {
const select = $("pvzSelect");
select.html("Выберите ПВЗ");
const res = await fetch(`/apiUrl/cdek.php?method=pvz&city_code=${cityCode}`);
const data = await res.json();
const options = data.map(pvz =>
$('<option>', {
value: pvz.code,
text: pvz.name
})
);
select.append(options);
}
Теперь при загрузке сайта запрашиваем метод fetchCities(), который сформирует наш селект. Он должен вернуть массив такого вида:

Ответ сервера со списком городов СДЭК
Далее при смене города будем запрашивать ПВЗ для этого города:
$("#citySelect").on("change", function() {
const cityCode = $(this).val();
if (cityCode) fetchPvz(cityCode);
});
Должен вернуться такой массив:

Ответ сервера со списком городов СДЭК
После этого во второй селект подгрузится список ПВЗ, и дальше можно обрабатывать эти данные по своему усмотрению:

Список городов и пунктов выдачи СДЭК
Накладная в СДЭК
После оформления заказа возможно придется формировать заказ в личном кабинете СДЭК. Для этого нужно на фронте его сформировать и отправить на бэкенд.
Фронтенд
// функция отправки заказа в СДЭК
async function sendOrderToSdek(orderData) {
const response = await fetch('/apiUrl/cdek-order.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(orderData)
});
const res = await response.json();
console.log('Ответ от PHP:', res);
return res;
}
// функция генерации ID заказа
function generateRandomId(length = 12) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// генерируем ID заказа
const orderId = generateRandomId();
// генерируем заказ
const cdekOrder = {
number: orderId,
tariff_code: 136, // из документации (склад-склад)
shipment_point: cdekPvz,
delivery_point: cdekPvz,
recipient: {
name: $('.js-username-input').val(), // имя клиента
phones: [
{
number: $('.js-tel-input').val() // номер телефона клиента
}
]
},
packages: [
{
number: "1",
weight: 500,
length: 10,
width: 10,
height: 5,
items: [
{
name: "Product name",
ware_key: "Product key",
payment: { value: 0 },
cost: 1000,
amount: 1,
weight: 500
}
]
}
]
}
Подробнее про формирование заказа можно почитать в документации https://apidoc.cdek.ru/#tag/order/operation/register_1
Бэкенд (cdek-order.php)
<?php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
echo json_encode([
'success' => false,
'error' => 'Нет входных данных'
]);
exit;
}
$clientId = 'YOUR_CLIENT_ID';
$clientSecret = 'YOUR_CLIENT_SECRET';
// функция создания заказа
function cdekCreateOrder($token, $orderData) {
$ch = curl_init('https://api.cdek.ru/v2/orders');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($orderData, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
"Authorization: Bearer $token"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
'httpCode' => $status,
'response' => json_decode($response, true),
'raw' => $response
];
}
// получаем токен (как в прошлом файле)
$token = getCdekToken($client_id, $client_secret, $cache_file);
if (!$token) {
echo json_encode(["error" => "Не удалось получить токен"]);
exit;
}
// создаём заказ
$result = cdekCreateOrder($token, $input);
// возвращаем результат фронту
echo json_encode($result, JSON_UNESCAPED_UNICODE);
Теперь заявка должна быть сформирована в личном кабинете СДЭК.

Сформированная накладная в личном кабинете СДЭК
Комментарии 0
Нет комментариев