Przejdź do treści

Dla programistów

Integracja z aplikacją InPost – Tale Commerce

Aplikacja InPost – Tale Commerce pozwala klientom wybrać punkt odbioru InPost bezpośrednio w checkoucie Shopify. Po złożeniu zamówienia dane wybranego punktu trafiają do obiektu zamówienia - odczytasz je przez Shopify webhooks lub Admin GraphQL API.

Z tego artykułu dowiesz się, jak:

  • odczytać identyfikator punktu odbioru z zamówienia,
  • rozpoznać dostawę Paczka w Weekend,
  • znormalizować nazwy metod dostawy na potrzeby raportowania.

Jak to działa

Wybrany punkt odbioru jest zapisywany w shipping line zamówienia. Odczyt sprowadza się do trzech kroków:

  1. Znajdź shipping line, w którym identyfikator przewoźnika jest równy 817bcd956c0dec08763dd1d56479cc14 - to stały identyfikator aplikacji InPost – Tale Commerce.
  2. Odczytaj pole code, np. INPOST-WAW77N.
  3. Usuń prefiks INPOST- - pozostała część (WAW77N) to identyfikator punktu odbioru.

Pola shipping line

Zamówienie zawiera tablicę shipping lines: shipping_lines w webhookach i shippingLines w GraphQL. Istotne pola:

Webhook GraphQL Opis
carrier_identifier carrierIdentifier identyfikator aplikacji - zawsze 817bcd956c0dec08763dd1d56479cc14
code code kod metody dostawy zawierający identyfikator punktu odbioru
title title nazwa metody dostawy widoczna dla klienta

Pola title i code nazywają się tak samo w obu API - różni się tylko zapis identyfikatora aplikacji (snake_case i camelCase).

Uwaga: Do identyfikacji punktu odbioru zawsze używaj pola code. Pole title to nazwa widoczna dla klienta - może zostać zmieniona w dowolnym momencie.

Odczyt danych zamówienia

Webhook

Payload webhooków zamówień (np. orders/create) zawiera tablicę shipping_lines:

{
  "shipping_lines": [
    {
      "carrier_identifier": "817bcd956c0dec08763dd1d56479cc14",
      "code": "INPOST-WAW77N",
      "title": "InPost Paczkomat 24/7 • 1.1 km • WAW77N"
    }
  ]
}

Dokumentacja webhooków Shopify: https://shopify.dev/docs/api/webhooks/latest

Admin GraphQL API

query GetOrder($id: ID!) {
  order(id: $id) {
    id
    name
    shippingLines(first: 5) {
      nodes {
        carrierIdentifier
        code
        title
      }
    }
  }
}

Dokumentacja obiektu Order: https://shopify.dev/docs/api/admin-graphql/latest/objects/Order

Wyodrębnianie identyfikatora punktu

Przykład w TypeScript:

const INPOST_APP_CARRIER_ID = "817bcd956c0dec08763dd1d56479cc14"
const INPOST_CODE_PREFIX = "INPOST-"

interface WebhookShippingLine {
  carrier_identifier: string | null
  code: string | null
  title: string
}

function getPickupPointId(shippingLine: WebhookShippingLine): string | null {
  if (shippingLine.carrier_identifier !== INPOST_APP_CARRIER_ID) {
    return null
  }

  const { code } = shippingLine

  if (!code?.startsWith(INPOST_CODE_PREFIX)) {
    return null
  }

  return code.slice(INPOST_CODE_PREFIX.length)
}

Przykładowe kody - Polska

Kod w code ID punktu Typ
INPOST-CSZ17M CSZ17M Paczkomat
INPOST-KRMA01BAPP KRMA01BAPP Paczkomat
INPOST-POP-BIA114 POP-BIA114 Punkt odbioru

Przykładowe kody - inne kraje

W przesyłkach międzynarodowych identyfikator punktu zaczyna się od kodu kraju:

Kod w code ID punktu
INPOST-AT981002P AT981002P
INPOST-BE041176 BE041176
INPOST-ES059572 ES059572
INPOST-FR033579 FR033579
INPOST-ITAAQ02468P ITAAQ02468P
INPOST-ITBAT44063M ITBAT44063M
INPOST-LU010779 LU010779
INPOST-NL022165 NL022165
INPOST-PT002296 PT002296
INPOST-UK00008334 UK00008334

Paczka w Weekend (tylko Polska)

Opcja Paczka w Weekend jest dostępna wyłącznie dla przesyłek krajowych w Polsce. Nie zmienia ona pola code - aby ją rozpoznać, sprawdź, czy pole title zawiera słowo “weekend”:

function isWeekendDelivery(shippingLine: { title: string }): boolean {
  return shippingLine.title.toLowerCase().includes("weekend")
}

Przykładowe wartości title:

  • InPost Paczkomat 24/7 • 1.1 km • WAW77N - standardowa dostawa
  • InPost Paczkomat 24/7 • 1.1 km • WAW77N • Paczka w Weekend - Paczka w Weekend

Normalizacja nazw metod dostawy

Nazwy metod dostawy generowane przez aplikację zawierają dystans i kod punktu odbioru, na przykład:

InPost Paczkomat 24/7 • 1.1 km • WAW77N
InPost Paczkopunkt • 0.5 km • POP-WAW722
Locker Mondial Relay • 1.1 km • FR020947
Points Relais® • 0.6 km • FR019857
Abholstation • 0.5 km • AT981002B
Postfiliale • 0.5 km • AT981002P
InPost Locker • 0.5 mi • UK00192101
InPost Shop • 0.4 mi • UK00253499

Jeżeli Twój system oferuje statystyki lub filtrowanie po nazwie metody dostawy, warto te nazwy ujednolicić. Wystarczy usunąć część zawierającą dystans i kod punktu:

function normalizeShippingName(title: string): string {
  return title.replace(/\d+(?:\.\d+)? (?:km|mi) • [\w-]+/g, "")
}

Wynik normalizacji:

Nazwa oryginalna Po normalizacji
InPost Paczkomat 24/7 • 1.1 km • WAW77N InPost Paczkomat 24/7
InPost Paczkomat 24/7 • 1.1 km • WAW77N • Paczka w Weekend InPost Paczkomat 24/7 • Paczka w Weekend
InPost Paczkopunkt • 0.5 km • POP-WAW722 InPost Paczkopunkt
Locker Mondial Relay • 1.1 km • FR020947 Locker Mondial Relay
Points Relais® • 0.6 km • FR019857 Points Relais®
InPost Locker • 0.5 mi • UK00192101 InPost Locker

Kompletny przykład

Poniższa funkcja przetwarza shipping line z webhooka lub GraphQL i zwraca wszystkie potrzebne informacje:

const INPOST_APP_CARRIER_ID = "817bcd956c0dec08763dd1d56479cc14"
const INPOST_CODE_PREFIX = "INPOST-"

interface WebhookShippingLine {
  carrier_identifier: string | null
  code: string | null
  title: string
}

interface GraphQLShippingLine {
  carrierIdentifier: string | null
  code: string | null
  title: string
}

type ShippingLine = WebhookShippingLine | GraphQLShippingLine

interface ParsedShippingLine {
  pickupPointId: string
  isWeekend: boolean
  originalName: string
  normalizedName: string
}

function normalizeShippingName(title: string): string {
  return title.replace(/\d+(?:\.\d+)? (?:km|mi) • [\w-]+/g, "")
}

function parseShippingLine(shippingLine: ShippingLine): ParsedShippingLine | null {
  const carrierId =
    "carrier_identifier" in shippingLine
      ? shippingLine.carrier_identifier
      : shippingLine.carrierIdentifier

  if (carrierId !== INPOST_APP_CARRIER_ID) {
    return null
  }

  const { code, title } = shippingLine

  if (!code?.startsWith(INPOST_CODE_PREFIX)) {
    return null
  }

  return {
    pickupPointId: code.slice(INPOST_CODE_PREFIX.length),
    isWeekend: title.toLowerCase().includes("weekend"),
    originalName: title,
    normalizedName: normalizeShippingName(title),
  }
}

Użycie z webhookiem (Express):

import express from "express"

const app = express()
app.use(express.json())

app.post("/webhooks/orders/create", (req, res) => {
  const order = req.body as { shipping_lines: WebhookShippingLine[] }

  for (const shippingLine of order.shipping_lines) {
    const result = parseShippingLine(shippingLine)

    if (result) {
      console.log(`Punkt odbioru: ${result.pickupPointId}`)
      console.log(`Paczka w Weekend: ${result.isWeekend}`)
      console.log(`Metoda dostawy: ${result.normalizedName}`)
    }
  }

  res.sendStatus(200)
})

Uwaga: W środowisku produkcyjnym pamiętaj o weryfikacji podpisu HMAC webhooka przed przetworzeniem danych.

Użycie z odpowiedzią GraphQL:

interface GetOrderResult {
  order: {
    shippingLines: {
      nodes: GraphQLShippingLine[]
    }
  } | null
}

const { order } = await shopifyGraphQL<GetOrderResult>(GET_ORDER_QUERY, { id: orderId })

for (const shippingLine of order?.shippingLines.nodes ?? []) {
  const result = parseShippingLine(shippingLine)

  if (result) {
    console.log(`Punkt odbioru: ${result.pickupPointId}`)
    console.log(`Paczka w Weekend: ${result.isWeekend}`)
    console.log(`Metoda dostawy: ${result.normalizedName}`)
  }
}