Интеграция службы доставки Почты России на сайт

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Интеграция службы доставки Почты России на сайт
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Интеграция службы доставки Почты России на сайт

Почта России — самая широкая сеть доставки в стране: отделения есть даже там, где нет других служб. API Почты России (pochta.ru) позволяет рассчитать стоимость, создать заказы, заказать вызов курьера и отслеживать посылки. API реализован на REST + JSON, авторизация через токен.

Авторизация

Почта России использует токены, которые выдаются в личном кабинете. Для отдельных методов — базовая авторизация (логин + пароль в base64), для других — Authorization: AccessToken.

class RussianPostClient
{
    private string $baseUrl = 'https://otpravka-api.pochta.ru/1.0';

    public function request(string $method, string $path, array $data = []): array
    {
        $credentials = base64_encode(
            config('services.russian_post.login') . ':' . config('services.russian_post.password')
        );

        $response = Http::withHeaders([
            'Authorization'    => 'AccessToken ' . config('services.russian_post.token'),
            'X-User-Authorization' => 'Basic ' . $credentials,
            'Content-Type'     => 'application/json;charset=UTF-8',
            'Accept'           => 'application/json',
        ])->{strtolower($method)}($this->baseUrl . $path, $data);

        if ($response->failed()) {
            throw new RussianPostApiException(
                "Pochta API error {$response->status()}: " . $response->body()
            );
        }

        return $response->json() ?? [];
    }
}

Нормализация адреса

Перед созданием заказа адрес нужно нормализовать — Почта России требует стандартизированных данных:

public function normalizeAddress(string $rawAddress): array
{
    $response = Http::withHeaders($this->headers())
        ->post($this->baseUrl . '/clean/address', [
            [
                'id'               => '1',
                'original-address' => $rawAddress,
            ]
        ]);

    $result = $response->json('0');

    if ($result['quality-code'] === 'UNDEF_05') {
        throw new \InvalidArgumentException('Адрес не найден: ' . $rawAddress);
    }

    return [
        'index'     => $result['index'],
        'region'    => $result['region'],
        'city'      => $result['place'],
        'street'    => $result['street'],
        'house'     => $result['house'],
        'flat'      => $result['room'] ?? '',
        'raw_name'  => $result['raw-address'],
    ];
}

Коды качества: GOOD — адрес точно определён, POSTAL_BOX — а/я, UNDEF_05 — не определён. Отображать покупателю форму с уточнением если код не GOOD.

Расчёт стоимости

public function calculateDelivery(
    string $fromIndex, // почтовый индекс отправителя
    string $toIndex,   // почтовый индекс получателя
    string $mailType,  // POSTAL_PARCEL, ECOM_MARKETPLACE и др.
    int    $weightGrams,
    int    $declaredValueKopecks = 0
): array {
    $response = $this->request('POST', '/tariff', [
        'index-from'      => $fromIndex,
        'index-to'        => $toIndex,
        'mail-category'   => 'ORDINARY', // ORDINARY, ORDERED, WITH_DECLARED_VALUE
        'mail-type'       => $mailType,
        'mass'            => $weightGrams,
        'payment'         => $declaredValueKopecks,
        'with-order-of-notice' => false,
        'with-simple-notice'   => false,
    ]);

    return [
        'total_kopecks' => $response['total-rate'] + ($response['total-vat'] ?? 0),
        'total_rubles'  => ($response['total-rate'] + ($response['total-vat'] ?? 0)) / 100,
        'delivery_days_min' => $response['delivery-time']['min-days'] ?? null,
        'delivery_days_max' => $response['delivery-time']['max-days'] ?? null,
    ];
}

Тип отправления POSTAL_PARCEL — обычная посылка. ECOM_MARKETPLACE — для маркетплейсов (нужен отдельный договор). EMS — ускоренная почта.

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

public function createOrder(Order $order): array
{
    $payload = [[
        'order-num'       => (string)$order->id,
        'address-type-to' => 'DEFAULT',
        'index-to'        => $order->normalized_index,
        'region-to'       => $order->normalized_region,
        'place-to'        => $order->normalized_city,
        'street-to'       => $order->normalized_street,
        'house-to'        => $order->normalized_house,
        'room-to'         => $order->normalized_flat ?? '',
        'mail-category'   => 'ORDINARY',
        'mail-type'       => 'POSTAL_PARCEL',
        'mass'            => (int)($order->total_weight_kg * 1000),
        'dimension'       => [
            'height' => $order->package_height * 10, // мм
            'length' => $order->package_length * 10,
            'width'  => $order->package_width * 10,
        ],
        'recipient-name'  => $order->recipient_name,
        'tel-address'     => preg_replace('/\D/', '', $order->recipient_phone),
        'payment'         => 0, // объявленная ценность в копейках
        'fragile'         => false,
        'with-fitting'    => false,
    ]];

    $response = $this->request('PUT', '/user/backlog', $payload);

    if (isset($response[0]['errors'])) {
        throw new RussianPostOrderException(
            'Order creation failed: ' . json_encode($response[0]['errors'])
        );
    }

    return [
        'result_id' => $response[0]['result-id'],
        'barcode'   => $response[0]['barcode'] ?? null,
    ];
}

Перевод в отправку и получение ШПИ

Созданный заказ находится в «бэклоге». Для получения штрихкода (ШПИ) нужно создать партию и добавить заказы в неё:

public function createBatch(string $mailType, string $mailCategory, string $fromIndex): string
{
    $response = $this->request('POST', '/batch', [
        'mail-type'     => $mailType,
        'mail-category' => $mailCategory,
        'send-date'     => now()->format('Y-m-d'),
        'shipment-point-index' => $fromIndex,
    ]);

    return $response['batch-name'];
}

public function addOrdersToBatch(string $batchName, array $orderIds): void
{
    $this->request('POST', "/batch/{$batchName}/backlog", $orderIds);
}

После добавления в партию заказам присваиваются ШПИ (14-значный штрихкод), который можно распечатать и наклеить на посылку.

Отслеживание по трек-номеру

Почта России предоставляет отдельный API для отслеживания (tracking.pochta.ru):

public function trackParcel(string $barcode): array
{
    // Трекинг-API использует SOAP или отдельный REST
    $response = Http::withToken(config('services.russian_post.tracking_token'))
        ->get('https://tracking.pochta.ru/tracking/api/v1/operations-history', [
            'Barcode'  => $barcode,
            'Language' => 'RUS',
        ]);

    return collect($response->json('OperationHistoryData.historyRecord'))
        ->map(fn($op) => [
            'date'       => $op['OperationParameters']['OperDate'],
            'type'       => $op['OperationParameters']['OperType']['Name'],
            'attribute'  => $op['OperationParameters']['OperAttr']['Name'],
            'city'       => $op['AddressParameters']['DestinationAddress']['PostalAddress']['City'] ?? '',
            'index'      => $op['AddressParameters']['DestinationAddress']['PostalAddress']['Index'] ?? '',
        ])
        ->toArray();
}

Трекинговый API — отдельные ключи доступа. Бесплатная квота — 100 запросов в сутки на один трек-номер, платные пакеты — от 1 000 до 100 000 запросов.

Партионная печать этикеток

public function printLabels(array $orderIds, string $sendingType = 'ONE_SIDED'): string
{
    $response = Http::withHeaders($this->headers())
        ->post($this->baseUrl . '/forms/orders/backlog?' . http_build_query([
            'print-type' => $sendingType,
        ]), $orderIds, ['Accept' => 'application/pdf']);

    return $response->body(); // PDF
}

Особенности работы с API

Индексы пунктов доставки нужно нормализовать через их же API — вручную вводимые покупателями индексы часто содержат опечатки или устаревшие данные. Максимальный вес посылки — 20 кг, объём — не более 2 м³.

Sandbox для тестирования: https://otpravka-api.pochta.ru/1.0 — тот же URL, тестовые credentials выдаются отдельно. Реальных посылок не создаётся, но ШПИ генерируются.

Сроки

Расчёт тарифа + нормализация адреса + создание заказов + этикетки — 6–8 рабочих дней. Сложнее, чем СДЭК или Boxberry, из-за двухшаговой модели (бэклог → партия), нормализации адресов и разделения трекинг-API. Полное тестирование — 2–3 дня.