Funkcje transformacyjne
Własny kod JavaScript uruchamiany przy każdym webhooku przed Shopify Flow: przekształcanie treści, wzbogacanie danych, odrzucanie żądań i odpowiedź nadawcy.
Funkcja mapowania pobiera wartości z żądania. Funkcja transformacji idzie o krok dalej: jest to Państwa własny kod JavaScript, uruchamiany przy każdym żądaniu przed przetworzeniem przez Shopify Flow, dzięki czemu mogą Państwo zmodyfikować zawartość żądania, wyszukać potrzebne informacje, zdecydować, czy w ogóle warto uruchamiać przepływ pracy w odpowiedzi na dane żądanie, lub samodzielnie udzielić odpowiedzi na żądanie.
Znajduje się w zakładce Funkcja webhooka. Pusty edytor oznacza, że funkcja jest wyłączona.
Kształt funkcji
export default async function transform(payload, ctx) {
// payload - the parsed request body (JSON, form or XML)
// return an object -> it becomes the payload for mapping and Flow
// return null -> nothing is sent to Flow, and nothing counts
return { ...payload, source: "warehouse" }
}Co oferuje zmienna ctx
ctx.request |
method, contentType, headers żądania (z zamaskowanymi danymi poufnymi) oraz query |
ctx.webhook |
id i name webhooka |
ctx.shop |
Państwa domena myshopify |
ctx.log(...) |
Zapisuje wiersz, który można odczytać w panelu testowym oraz w historii |
await ctx.fetch(url, init) |
Wywołuje publiczny interfejs API |
await ctx.shopify(query, variables) |
Odczytuje dane ze sklepu za pomocą Admin GraphQL |
ctx.storage |
Zachowuje niewielkie wartości pomiędzy kolejnymi przebiegami (patrz poniżej) |
ctx.respond(body, options) |
Natychmiast odbiera połączenie |
Przekształcanie ładunku
Najczęstsze zastosowanie: przekształcenie struktury danych nadawcy w kilka wartości potrzebnych w Państwa przepływie pracy.
export default async function transform(payload) {
const order = payload.data.attributes
return {
orderNumber: String(order.number),
email: order.customer.email.toLowerCase(),
total: Number(order.total_cents) / 100,
}
}Usuwanie niepotrzebnych żądań
Zwróć wartość null, a żądanie zostanie zatrzymane na tym etapie: nie nastąpi uruchomienie Shopify Flow, nie zostanie utworzony wpis w historii, a nic nie zostanie zaliczone na poczet Państwa planu. Wywołujący otrzyma kod 200 wraz z { "skipped": true }, więc nie podejmie ponownej próby.
export default async function transform(payload, ctx) {
if (payload.status !== "paid" || payload.total < 100) {
ctx.log("skipping", payload.id, payload.status, payload.total)
return null
}
return payload
}Zapamiętywanie informacji pomiędzy seriami
ctx.storage to niewielka baza danych typu klucz-wartość, która należy do Państwa sklepu. Jest to narzędzie służące do sprawdzania: „czy widziałem to już wcześniej?”: po otrzymaniu zdarzenia zapisuje się identyfikator, a następnie pomija się kolejne żądanie zawierające ten sam identyfikator, nawet jeśli nadejdzie ono kilka dni później.
| Zadzwoń | Czy |
|---|---|
await ctx.storage.get(key) |
Wartość zapisana w pamięci lub null |
await ctx.storage.set(key, value) |
Zapisuje dowolną wartość JSON, zastępując dotychczasową |
await ctx.storage.delete(key) |
Usuwa go; zwraca wartość true, jeśli istniał |
await ctx.storage.list({ prefix, limit, cursor }) |
Najważniejsze nazwy i rozmiary, strona po stronie |
export default async function transform(payload, ctx) {
const key = `seen:${payload.id}`
if (await ctx.storage.get(key)) return null
await ctx.storage.set(key, { at: Date.now() })
return payload
}Wzbogacanie o dane ze sklepu
ctx.shopify wykonuje zapytania GraphQL typu „tylko do odczytu” w panelu administracyjnym Państwa sklepu, dzięki czemu przepływ pracy może rozpocząć się na podstawie danych, do których nadawca nigdy nie miał dostępu. Widzi on wyłącznie to, na co Państwo zezwolą: należy przyznać niezbędne zakresy uprawnień w sekcji Dostęp do danych sklepu na karcie „Funkcja”. Domyślnie żadne uprawnienia nie są przyznane, a mutacje są odrzucane.
export default async function transform(payload, ctx) {
const data = await ctx.shopify(
`query($q: String!) {
productVariants(first: 1, query: $q) { nodes { id title price } }
}`,
{ q: `sku:${payload.sku}` },
)
const variant = data.productVariants.nodes[0]
if (!variant) return null
return { sku: payload.sku, variantId: variant.id, price: variant.price }
}Samodzielne odebranie połączenia
Funkcja ctx.respond() natychmiast wysyła odpowiedź, co sprawia, że webhook staje się niewielkim punktem końcowym API: weryfikuje dane, oblicza wynik i odpowiada w ramach jednego żądania. Shopify Flow nadal działa niezależnie od tego, co Państwo zwrócą.
export default async function transform(payload, ctx) {
const ok = typeof payload.email === "string" && payload.email.includes("@")
ctx.respond({ accepted: ok }, { status: ok ? 200 : 422 })
return ok ? payload : null
}Testy
Panel Test w zakładce „Funkcja” uruchamia kod w edytorze - wraz z niezapisanymi zmianami - na przykładowej treści żądania. Wyświetla wartość zwracaną, odpowiedź, jaką wysłałaby Państwa funkcja, pola Shopify Flow, które generuje, wiersze dziennika oraz czas trwania. Shopify Flow nie zostaje uruchomiony, nic nie jest zapisywane w historii, a operacja ta nie wlicza się do limitu Państwa planu. Wywołania do magazynu danych są jednak rzeczywiste: podczas testu odczytywany i zapisywany jest ten sam sklep, co w przypadku rzeczywistych żądań.
Gdy funkcja zakończy się niepowodzeniem
Jeśli Państwa kod wygeneruje wyjątek, przekroczy limit czasu lub zwróci wynik, którego nie da się wykorzystać, żądanie zostanie odrzucone z kodem błędu 422, a niepowodzenie zostanie odnotowane w sekcji Historia wraz z opisem błędu i Państwa wpisami z dziennika, dzięki czemu będą Państwo mogli sprawdzić, co się stało. Proszę poprawić kod i ponownie odtworzyć ten wpis: podczas ponownego odtworzenia zostanie uruchomiona nowa wersja kodu.
Ograniczenia
- 5 sekund i 64 MB na jedno uruchomienie oraz 50 000 znaków kodu.
- Brak pakietów npm. Jedynym rozwiązaniem jest użycie funkcji
ctx.fetch, przy czym adresy wewnętrzne lub prywatne są odrzucane. ctx.shopifypozwala na 10 wywołań na jedno uruchomienie; są to wyłącznie zapytania, ograniczone do zakresów, na które udzielili Państwo uprawnień.- Każde uruchomienie, które dociera do Shopify Flow, stanowi standardowe wywołanie i jest wliczane do limitu przewidzianego w Państwa planie. Pominięte żądanie nie jest wliczane.
